tags:

views:

94

answers:

4

I have these little cursor shaped forms that I need to be on Top of everything, all the time...
FormStyle is already fsStayOnTop
I use this code:

 SetWindowPos(tempCursor.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE );

and this (even though I don't exactly know what it does):

procedure TCursorFrm.CreateParams(var Params: TCreateParams);
const
   WS_EX_NOACTIVATE = $8000000;
begin
   inherited;
   Params.ExStyle := Params.ExStyle + WS_EX_NOACTIVATE;
end;

but I still cannot get my forms to be on Top of TMenuItems. How can I make my forms stay on top of everything?

+4  A: 

I think that's as good as you're going to get. If your form stayed on top of menus, then users wouldn't be able to see a menu when they opened it. Doing something like that, especially when the system doesn't make it available through any easy means, borders on the malicious, or at least feels that way. You don't want your users to think that your program is malicious, so my advice would be to not try to do this in the first place.

Mason Wheeler
Well, it's supposed to be a cursor (multiple cursors for multiple mice), that's why it should be on top. It's kinda weird that the cursor is behind the MenuItems. :( (Oh, and I don't think the users will think it's malicious because it doesn't at all look like a regular form, it looks like a regular cursor)
Dian
Oh, it's a cursor? in that case, why are you trying to implement a cursor with a *form?* I'm sure there's a simpler way. Not sure what that way is, but there has to be one...
Mason Wheeler
Because it was suggested to me in another question and in all fairness it works pretty well except for the Menu problem. My first attempt was painting the cursor on the Screen canvas, it was a nightmare (lots and lots of problems). Haven't really found another way aside from those two.
Dian
Ummm... will you "cursor" be above my full screen games? Then... curse you! :D
Alexander
@Alexander: hahaha! No, the cursors will only be present when my application (which is a multiple user typing and multiple choice app) is running.
Dian
+1  A: 

Quick, slightly hacky fix: Call this from an Timer, 10 times a second:

BringWindowToTop(Handle)

Just tried it and it works! Maybe you can find a way to make it less "brute force", but I'm not sure how.

Cosmin Prund
Tried it (as you suggested) with a timer. I can't access the Menu anymore, when I click the Menu, the Items appear for a split second then it's gone.
Dian
What "Items"? Is the menu disappearing? If so, please show some code, maybe you're somehow stealing focus from the menu? In my test I simply made a "stay on top" window and right-clicked in a text editor, causing a popup menu to show up exactly under the form. It worked as expected, the menu didn't go away; Of course, I wasn't trying to emulate an secondary mouse cursor...
Cosmin Prund
Yep, the MenuItems disappear. Placed this: BringWindowToTop(Cursor[I].Handle) in a for-loop that executes every second. Yeah, I think I'm stealing focus from the menu.
Dian
Why are you doing that in a for loop? Place an timer somewhere, set it's interval to "100" and call BringWindowToTop from there. And the focus problem, if indeed that's what's happening, is a different problem.
Cosmin Prund
It's a for loop because the cursors are stored in an array (of records... the cursor is assigned to a specific user thus a specific record). And yeah, it steals focus from the Menu and from the MainForm.
Dian
+2  A: 

I think that you can look into DirectX. I believe that it allows overlays over primary image. You can open it in non-exlusive mode and draw overlay over desktop. But I'm NOT sure about it. Just a guess.

Alexander
+1  A: 

This has to be the ultimate, or worst, piece of hackery I'll publish.

  1. Set your FormStyle to be fsStayOnTop (This step may not actually be necessary)
  2. Drop a TTimer on your form and set it's interval to 100
  3. In the OnTimer event place the following code:

    if visible then SetWindowPos(Self.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or SWP_NOACTIVATE);

I'm using this in one of my projects and it seems to work alright.

Ryan J. Mills
Wow. it works! really hacky but it works. Thanks. :D
Dian