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 |
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 |