3

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?

Dian
  • 1,187
  • 3
  • 18
  • 35

6 Answers6

4

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
  • 82,511
  • 50
  • 270
  • 477
  • 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 Jul 14 '10 at 03:05
  • 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 Jul 14 '10 at 03:16
  • 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 Jul 14 '10 at 03:22
  • Ummm... will you "cursor" be above my full screen games? Then... curse you! :D – Alex Jul 14 '10 at 09:08
  • @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 Jul 14 '10 at 09:54
4

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.

Vivian Mills
  • 2,552
  • 14
  • 19
  • 4
    I looked up in the dictionary and 'hacky' does not accurately describe how hacky this hack it is. We need a new word for this. – Gabriel Oct 08 '15 at 19:32
2

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
  • 25,498
  • 2
  • 60
  • 104
  • 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 Jul 14 '10 at 06:50
  • 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 Jul 14 '10 at 07:04
  • 1
    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 Jul 14 '10 at 07:12
  • 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 Jul 14 '10 at 07:19
  • 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 Jul 14 '10 at 07:31
2

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.

Alex
  • 5,477
  • 2
  • 36
  • 56
0

or instead of the SetWindowPos command - try this:

if visible then form1.SetFocus;
0

I use the following sequence of instructions in the OnShow event handler:

SetForegroundWindow(Handle);
BringWindowToTop(Handle);