The program listed below is the start of my current project. It is a simple program, it has a simple opaque window with two transparent and click-through rectangles on it. The problem is that when I first run the program and move the cursor into the window area, I get the spinning circle busy cursor. If I move out of the window, and wait a few seconds before moving back into the window, the cursor is okay.
I'm sure I'm having a senior moment and forgetting some simple windows must do somewhere, but I can't seem to find it.
If someone can see what message I need to service to avoid this problem, please let me know.
This is the stripped down code. The window has no title bar, so just press a key to exit.
.686
.model flat, stdcall
option casemap:none
include windows.inc
include kernel32.inc
include user32.inc
include gdi32.inc
includelib kernel32.lib
includelib user32.lib
includelib gdi32.lib
inv equ INVOKE
.data
ClassName db "WindowHoleClass", 0
WindowName db "Window with click-through Rectangles", 0
rect1 RECT <50, 50, 150, 150> ; First rectangle (x1, y1, x2, y2)
rect2 RECT <200, 100, 300, 200> ; Second rectangle (x1, y1, x2, y2)
wc WNDCLASS <CS_HREDRAW or CS_VREDRAW,
offset WndProc,0,0,0,0,0,,0,offset ClassName>
backcolor dd 0f0f0fh ; background (view blocking) color
transparentcolor dd 020202h ; must be different than backcolor
.data?
msgx MSG <>
ps PAINTSTRUCT <>
hbBrush dd ? ; background brush
htBrush dd ? ; transparent brush
hdc dd ? ; device construct
hwnd dd ?
hinst dd ?
.code
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.if uMsg == WM_PAINT
; Begin painting
inv BeginPaint, hWnd, addr ps
mov hdc, eax
; Clear the background
inv FillRect, hdc, addr ps.rcPaint, hbBrush
; Draw the transparent rectangles
inv SelectObject, hdc, htBrush
inv Rectangle, hdc, rect1.left,rect1.top,rect1.right,rect1.bottom
inv Rectangle, hdc, rect2.left,rect2.top,rect2.right,rect2.bottom
inv EndPaint, hWnd, addr ps
.elseif uMsg== WM_KEYDOWN
inv PostQuitMessage,0
.elseif uMsg == WM_DESTROY
inv PostQuitMessage,0
.else
inv DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
xor eax, eax
ret
WndProc endp
Program:
inv GetModuleHandle, 0 ;get the instance handle
mov hinst,eax
; Register window class
mov wc.hInstance,eax
inv RegisterClass, addr wc
; Create window
inv CreateWindowEx, WS_EX_LAYERED,
offset ClassName, offset WindowName,
WS_POPUP or WS_VISIBLE or WS_BORDER,
100, 100, 500, 300, 0, 0, hinst, 0
mov hwnd, eax ; save window handle
; Set transparency color for drawing rectangles
inv SetLayeredWindowAttributes,hwnd,transparentcolor,0,LWA_COLORKEY
inv CreateSolidBrush, backcolor
mov hbBrush, eax
inv CreateSolidBrush, transparentcolor
mov htBrush, eax
; Message loop
.repeat
inv GetMessage, addr msgx, 0, 0, 0
.break .if !eax
inv TranslateMessage, addr msgx
inv DispatchMessage, addr msgx
.until 0
inv DeleteObject, hbBrush ; cleanup
inv DeleteObject, htBrush ; cleanup
mov eax, msgx.wParam
inv ExitProcess, 0
end Program
Holy Holey windows, Batman! :tongue:
It seems to work okay, but...
Sometimes the cursor would change to the 'busy' cursor while over the window as you had mentioned, but not always.
Otherwise I have tested the intended functionality and it works.
Running in ollydbg, I can click on things in ollys window. (inside the 'holes')
On the desktop, I can rearrange icons under the program window (inside the 'holes'.) :thup:
Try SetCursor??
I have seen this before in some of my own programs.
invoke LoadCursor, NULL, IDC_ARROW
invoke SetCursor, eax
In testing, I placed that code just after window creation code (Next line after "mov hwnd, eax").
It's always a good idea to give your WNDCLASS a cursor and icon :badgrin:
That was it sinsi, Thanks!
insert
inv LoadCursor, 0, IDC_ARROW ; important
mov wc.hCursor,eax
before RegisterClass and everything is good.
The busy indicator must have been windows thinking about what to use :)
Quote from: sinsi on November 20, 2024, 07:50:52 AMIt's always a good idea to give your WNDCLASS a cursor and icon
It happens, and all too often, where that detail is forgotten. :biggrin:
Quote from: jimg on November 20, 2024, 08:05:41 AMThat was it sinsi, Thanks!
insert
inv LoadCursor, 0, IDC_ARROW ; important
mov wc.hCursor,eax
before RegisterClass and everything is good.
The busy indicator must have been windows thinking about what to use :)
Wow; I think y'all just solved a problem of long standing that a lot of my programs have, showing a busy/waiting cursor for no good reason. Thanks!
And I totally believe your last sentence there explains why this happens.
Quote from: jimg on November 20, 2024, 08:05:41 AMThe busy indicator must have been windows thinking about what to use :)
More like waiting for you to pick one :biggrin:
Wait a sec: now I'm not so sure about this.
Why would not having a default cursor defined for a window cause the busy cursor to appear? Wouldn't it default to the regular old arrow? Or would registering the class with a NULL cursor cause Windows to show busy when you don't set a cursor like it's expecting you to? (Which tells me that in that case the busy cursor IS the default cursor.)
What else could cause the busy cursor? Could it be that no window is currently selected, or activated, or whatever? Does the cursor change if you click on the window to select it?
Of course the fact that setting a default cursor for the window class made the busy cursor go away does point to that being the cause of the problem, but is that really the case?
QuoteTipo: HCURSOR
Identificador del cursor de clase. Este miembro debe ser un identificador para un recurso de cursor. Si este miembro es NULL, una aplicación debe establecer explícitamente la forma del cursor cada vez que el mouse se mueve a la ventana de la aplicación.
En inglese, por favor:
QuoteClass cursor identifier. This member must be an identifier for a cursor resource. If this member is NULL, an application must explicitly set the shape of the cursor each time the mouse is moved to the application window.