简体   繁体   中英

Keep my form above the taskbar?

My overall goal is to render a second (or third, fourth...) mouse cursor. To this end, I have created a frameless, topmost, transparent window. I can draw on this window (I have 4 buttons on it to show that it's properly covering the whole desktop) - but when I click on the taskbar, it is brought to the top and overlays my buttons and drawn line.

How can I keep my window above the taskbar?

Alternatively, is there a way that I can draw on the "final" version of the screen?

Here's the code from my .Designer.cs file:

this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.BackColor = System.Drawing.Color.White;
this.CausesValidation = false;
this.ClientSize = new System.Drawing.Size(332, 332);
this.ControlBox = false;
this.Controls.Add(this.button4);
this.Controls.Add(this.button3);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Screen";
this.ShowIcon = false;
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.WindowsDefaultBounds;
this.TopMost = true;
this.TransparencyKey = System.Drawing.Color.White;

Without analysing the exact motivation of doing this and whether this approach is the best way through, you should note that the taskbar's behaviour is equivalent to the one of any other window: TopMost can be used without any restriction. On the other hand, it is considered outside the "WorkingArea" and thus, depending upon the properties you are using, it might be ignored. Take a look at the sample codes below to understand this better.

Main Form covering all the available space above the taskbar:

this.ClientSize = new System.Drawing.Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height);
this.Location = new Point(Screen.PrimaryScreen.WorkingArea.Left, Screen.PrimaryScreen.WorkingArea.Top);

Main Form covering the whole available space of the screen:

this.ClientSize = new System.Drawing.Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
this.Location = new Point(Screen.PrimaryScreen.WorkingArea.Left, Screen.PrimaryScreen.WorkingArea.Top);

Thus, you can locate your form on top of the taskbar without any problem by bearing the mind that it represents the difference between WorkingArea and Bounds of the screen.

CLARIFICATION: this answer highlights what might be the reason for the taskbar to be treated differently than any other part of the screen. It does not imply that you have to make your form as big as the whole screen to put it over the taskbar; you can put it over the taskbar whenever you want with an as small size as you wish. What you have to bear in mind is that WorkingArea does not provide the whole dimensions of the screen, but just the area ABOVE the taskbar; if you want to bring the taskbar into consideration, consider Bounds .

I'll go with varocarbas answer,but there is something that i want to add which i think might be useful.

A few things are there that i guess may be helpful,when i read your question the first idea that struck my mind was to create a GlobalHook to monitor message WM_CBT ,this message is send to GlobalHook procedure when the system is about to Maximize,Minimize,Restore or Focus a Window.When any hook is trapped you can override any required events to block that window from becoming the topmost window,thus giving your Form a chance to remain the topmost Window.This method will be highly helpful if it worked as i am expecting.

If you are interested in this, here are the methods that are required to make a GlobalHook work. SetWindowsHookEx() ,used to tell the system to create a GlobalHook.
HookProc ,Represents the method called when a hook catches a monitored event.
HookType ,Enumerates the valid hook types passed into a call to SetWindowsHookEx.
CallNextHook .If using interoperability is messy,try this open source library that contains WindowsAPI functions in a managed wrapper.Hope this helps you,meanwhile i'm also trying to get the stuff working for you.

I've been struggling for a few hours with this same problem. I thought of a nice solution: just change the bottom padding of the form dynamically whenever the form is maximized.

If Me.WindowState = FormWindowState.Maximized then
    Dim pd As New Padding
    pd.Left = Me.Padding.Left
    pd.Right = Me.Padding.Right
    pd.Top = Me.Padding.Top
    pd.Bottom = Me.Height - Screen.PrimaryScreen.WorkingArea.Height
    Me.Padding = pd
end if

This way the form is not above the taskbar, but at least your controls are! Note: in designing your forms you can leave the bottom-padding 0. If you want your form to be able to minimize/normal resize, then you may want to reset the bottom padding to 0 in another form event.

I actually found the solution about 15 minutes after I posted. (Isn't that always the way? Research for hours, but as soon as you ask for help, you figure it out on your own. :)

I have an event that is calling my code with position updates. If I simply call "BringToFront" in this event, it works just fine. The event is called many times per second, but if I throttle my behavior back to 1/4 second, it still works great.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM