Windows Develop Bookmark and Share   
 index > Windows Forms General > C# How to make a form click-thru-able (hard to explain in one line!)
 

C# How to make a form click-thru-able (hard to explain in one line!)

Hi,

I was considering making a cursor replacement application in C#. To do this i made a form with a PictureBox and a Timer. The Timer would synchronize the form's position to the cursor coordinates. The form was using a TransparencyKey and was TopMost. However, when I click anywhere, the form handles the mouse event, meaning that I can't do anything with the computer other than click on the cursor (not really that useful!!).... how can I make it so that clicks "go through" the form?

OR! Is there some way in C# of drawing images, etc. beyond the form's surface?

Thanks in advance!
- Javawag
Javawag  Monday, December 18, 2006 12:00 PM

-

Paul Louth  Monday, December 18, 2006 12:06 PM

Try using  a ListView for drawing a grid of images.  As for clicking the form.  Just add a click event:

this.Click+=new EventHandler(MainForm_Click);

Paul Louth  Monday, December 18, 2006 12:06 PM
Sorry, I think you've misunderstood my question... As the application I am making is just a cursor replacement app, what I want is that when I click, neither the form nor the PictureBox should handle the click event. The entire application needs to ignore the click event and allow whatever application is under it handle the click event (So that when I click, the cursor replacement app doesn't handle the click, but the application under the cursor does).

I hope this makes it a bit clearer
- Javawag


Javawag  Monday, December 18, 2006 12:19 PM

I see what you're trying to do now. And I don't think it's possible, or even the best way. You can replace cursors like this:

Bitmap cursorBitmap = (Bitmap)Bitmap.FromFile("MyCursorImage.bmp");
IntPtr cursorBitmapHicon = cursorBitmap.GetHicon();
Cursor.Current = new Cursor(cursorBitmapHicon);

Paul Louth  Monday, December 18, 2006 2:42 PM
Thanks! This kind of works... it changes the cursor as I wanted but of course only when it is over a visible part of the current form (which is totally transparent using TransparencyKey)... so it doesn't really work for my purposes due to the way it works.

So, it seems what i'm trying to do is impossible ! The only alternative would be drawing directly onto the screen rather than onto the Form. Is this possible? ie can you get a Graphics object of the entire screen surface rather than just that of a Form?

Thanks again,
-Javawag
Javawag  Monday, December 18, 2006 3:09 PM
You could try using the WinAPI SetCursor instead?
Paul Louth  Monday, December 18, 2006 3:19 PM
Ooooh... can that take a bitmap as an input as the previous one could?

- Javawag
Javawag  Monday, December 18, 2006 3:35 PM
Basically, what you'd have to do is receive the click event yourself, and then dispatch a simulated one to the proper window.
James Curran  Monday, December 18, 2006 5:04 PM
Now we're getting somewhere! In theory that sounds do-able... any idea of how to code that? Would I need to get the handle of the window or something like that to do this?

- Javawag
Javawag  Monday, December 18, 2006 5:28 PM

I neglected mentioning that part, because it's kinda tricky....

To Handle it, we need a bit more information: Are we covering just one app, or a random portion of the screen, covering potenially several windows? If the latter, it get very involved. If just one, then we need to know if it's a .Net app or a Win32 app.

James Curran  Monday, December 18, 2006 7:27 PM
Yeaaah it would be the latter... which undoubtedly makes it a lot more difficult!

-Javawag
Javawag  Monday, December 18, 2006 7:42 PM

This could be too late but someone might find this useful. You can create a layered window as follows:

[DllImport("user32.dll", SetLastError = true)]

private static extern UInt32 GetWindowLong(IntPtr hWnd, int nIndex);

[DllImport("user32.dll")]

static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

[DllImport("user32.dll")]

static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);

public const int GWL_EXSTYLE = -20;

public const int WS_EX_LAYERED = 0x80000;

public const int WS_EX_TRANSPARENT = 0x20;

public const int LWA_ALPHA = 0x2;

public const int LWA_COLORKEY = 0x1;

public Form1()

{

InitializeComponent();

SetWindowLong(this.Handle, GWL_EXSTYLE,

(IntPtr)(GetWindowLong(this.Handle, GWL_EXSTYLE) ^ WS_EX_LAYERED ^ WS_EX_TRANSPARENT));

// set transparency to 50% (128)

SetLayeredWindowAttributes(this.Handle, 0, 128, LWA_ALPHA);

this.TopMost = true;

}

  • Proposed As Answer byTyranin Thursday, October 01, 2009 11:12 AM
  •  
Phil Waters  Friday, December 05, 2008 12:31 PM
Phil Waters said:

SetWindowLong(this.Handle, GWL_EXSTYLE,

(IntPtr)(GetWindowLong(this.Handle, GWL_EXSTYLE) ^ WS_EX_LAYERED ^ WS_EX_TRANSPARENT));



This, I think, must read

SetWindowLong(this.Handle, GWL_EXSTYLE,

(IntPtr)(GetWindowLong(this.Handle, GWL_EXSTYLE) | WS_EX_LAYERED | WS_EX_TRANSPARENT));

| instead of ^, beacuse you want to set the flags, rather than toggle them...


But nevertheless thank you for the code! :-)


Cheers

Dany

DanyR  Tuesday, March 17, 2009 12:27 PM
This code is perfect, thank you very much!
Do Crabs Think We Walk Sideways??
Tyranin  Thursday, October 01, 2009 11:12 AM

You can use google to search for other answers

Custom Search

More Threads

• Listview with Watermark
• MissingManifestResourceException in a form of another project
• Closing my form causes order of other application windows to change
• C# 2008 - Basic use of a TreeView control
• XP themes are not being applied to my Form controls.
• Passing Object from form to form.
• C# vs2005 forms ToolStripMenuItem ShowDropDown doesn't list choices
• want to integrate F7 key as a shortcut key to initiate grammar checker.
• resize panel in tabcontrol
• DataGridView format part of a cell's text