There are some windows which when are dragged around the screen, will get "glued" to certain edges of the screen. For example, if you drag the window to the rightmost point of the screen, it will get glued to the rightmost edge of the screen. I thought it was fun to make something like this in MASM. Besides, it had been a long time since I had coded anything in MASM with Win32 API so here it is. Ladies and gentlemen, please welcome: Sticky Form:
.386
.MODEL FLAT, STDCALL
OPTION CASEMAP:NONE
INCLUDE Windows.inc
INCLUDE User32.inc
INCLUDE Kernel32.inc
INCLUDELIB User32.lib
INCLUDELIB Kernel32.lib
INITIAL_WINDOW_WIDTH EQU 200
INITIAL_WINDOW_HEIGHT EQU INITIAL_WINDOW_WIDTH
STICKY_FACTOR EQU 5
.DATA
ClassName DB "#32770", 0
WindowName DB "Sticky Form", 0
Messages MSG <>
.DATA?
hInstance HINSTANCE ?
CommandLine LPSTR ?
MainForm HWND ?
WindowClass WNDCLASSEX <>
ScreenDevice DEVMODE <>
.CODE
; ---------------------------------------------------------------------------
WndProc PROC hWnd:DWORD, Msg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL WindowWidth:DWORD
LOCAL WindowHeight:DWORD
LOCAL ScreenWidth:DWORD
LOCAL ScreenHeight:DWORD
MOV ESI , Msg
@@:
CMP ESI , WM_CLOSE
JNE @F
INVOKE ExitProcess, 0
@@:
CMP ESI , WM_MOVING
JNE @F
ASSUME EBX:PTR DEVMODE
MOV EBX , OFFSET ScreenDevice
INVOKE EnumDisplaySettings, NULL, 0FFFFFFFFh, EBX
MOV EAX , DWORD PTR .dmPelsWidth
MOV EDX , DWORD PTR .dmPelsHeight
MOV ScreenWidth , EAX
MOV ScreenHeight , EDX
ASSUME ESI:PTR RECT
MOV ESI , lParam
MOV EAX , DWORD PTR .left
MOV EBX , DWORD PTR .right
MOV ECX , DWORD PTR .top
MOV EDX , DWORD PTR .bottom
MOV EDI , EBX
SUB EDI , EAX
MOV WindowWidth , EDI
MOV EDI , EDX
SUB EDI , ECX
MOV WindowHeight , EDI
; EAX = left
; EBX = right
; ECX = top
; EDX = bottom
; ESI = RECT
; EDI = Free
@@CheckStickingToTheLeftofScreen:
CMP EAX , 0 + STICKY_FACTOR
JG @@CheckStickingToTheRightofScreen
MOV DWORD PTR .left , 0000000h
MOV EDI , EBX
SUB EDI , EAX
MOV DWORD PTR .right , EDI
@@CheckStickingToTheRightofScreen:
MOV EDI , ScreenWidth
SUB EDI , STICKY_FACTOR
CMP EBX , EDI
JL @@CheckStickingToTheTopofScreen
MOV EDI , ScreenWidth
MOV DWORD PTR .right , EDI
SUB EDI , WindowWidth
MOV DWORD PTR .left , EDI
@@CheckStickingToTheTopofScreen:
CMP ECX , 0 + STICKY_FACTOR
JG @@CheckStickingToTheBottomofScreen
XOR EDI , EDI
MOV DWORD PTR .top , EDI
MOV EDI , WindowHeight
MOV DWORD PTR .bottom , EDI
@@CheckStickingToTheBottomofScreen:
MOV EDI , ScreenHeight
SUB EDI , STICKY_FACTOR
CMP EDX , EDI
JL @F
ADD EDI , STICKY_FACTOR
MOV DWORD PTR .bottom , EDI
SUB EDI , WindowHeight
MOV DWORD PTR .top , EDI
@@:
INVOKE DefWindowProc, hWnd, Msg, wParam, lParam
RET
WndProc ENDP
; ---------------------------------------------------------------------------
START:
INVOKE GetModuleHandle, NULL
MOV hInstance, EAX
MOV ESI , EAX
ASSUME EDI:PTR WNDCLASSEX
MOV EDI , OFFSET WindowClass
INVOKE RtlZeroMemory, EDI, SIZEOF WNDCLASSEX
MOV DWORD PTR .cbSize , SIZEOF WNDCLASSEX
MOV DWORD PTR .hbrBackground , COLOR_BTNFACE + 1
MOV DWORD PTR .lpszClassName , OFFSET ClassName
MOV DWORD PTR .lpfnWndProc , OFFSET WndProc
MOV DWORD PTR .hInstance , ESI
INVOKE LoadCursor, 0, IDC_ARROW
MOV DWORD PTR .hCursor , EAX
INVOKE LoadIcon, 0, IDI_APPLICATION
MOV DWORD PTR .hIcon , EAX
MOV DWORD PTR .hIconSm , EAX
INVOKE RegisterClassEx, OFFSET WindowClass
; Position the screen in the center of the screen
ASSUME EBX:PTR DEVMODE
MOV EBX , OFFSET ScreenDevice
INVOKE EnumDisplaySettings, NULL, 0FFFFFFFFh, EBX
MOV EAX , DWORD PTR .dmPelsWidth
SHR EAX , 00000001h
SUB EAX , (INITIAL_WINDOW_WIDTH SHR 1)
MOV EDX , DWORD PTR .dmPelsHeight
SHR EDX , 00000001h
SUB EDX , (INITIAL_WINDOW_HEIGHT SHR 1)
; EAX = Center.X
; EDX = Center.Y
INVOKE CreateWindowEx, 0, OFFSET ClassName, OFFSET WindowName, WS_VISIBLE OR WS_OVERLAPPEDWINDOW, \
EAX, EDX, INITIAL_WINDOW_WIDTH, INITIAL_WINDOW_HEIGHT, 0, 0, ESI, 0
MOV DWORD PTR , EAX
MOV ESI , EAX
INVOKE ShowWindow , EAX, SW_SHOWNORMAL
INVOKE UpdateWindow , ESI
@@:
INVOKE GetMessage, OFFSET Messages, 0, 0, 0
TEST EAX , EAX
JZ @F
INVOKE TranslateMessage, OFFSET Messages
INVOKE DispatchMessage, OFFSET Messages
JMP @B
@@:
INVOKE ExitProcess, 0
END START
Is this more like those "snap-to" windows, ones that ride along a screen edge or something else completely?
Some of them stick to any adjacent window but this one only sticks to the borders of the screen and not any window. It could be extended to do that though. One more thing that the program does is that it won't get dragged outside the screen. :thumbsup:
handles multiple monitors?
handles multiple monitors?
Well I don't have more than one monitor so I would say "yes it does" :lol" I don't really know if the code works on multiple monitors. Shouldn't the Operating System handle that for the application?
handles multiple monitors?
Well I don't have more than one monitor so I would say "yes it does" :lol" I don't really know if the code works on multiple monitors. Shouldn't the Operating System handle that for the application?
Depends on whether you're querying screen/desktop dimensions at any times... which you probably do if you support snapping to screen edge :)
There's basically two ways that multi-monitor configs can be handled: stretching your desktop across all screens (meaning an app maximizes pretty uglily, you get start/process bar on both monitors, etc), or "independent" where your app maximizes to only one monitor... it's the "independent" mode some applications have trouble handling.
Depends on whether you're querying screen/desktop dimensions at any times... which you probably do if you support snapping to screen edge :)
Yes I am doing that with every WM_MOVING message that is sent to the window :P
Well from your descriptions, I believe there are certain techniques that have to be used to allow this application to be working on multiple screens. I haven't tried it on multiple screens as I don't have them but I would appreciate it if somebody could try it out and give me some feedback.
I'm on a laptop right now, but I have multiple monitors on my main box, so I can give it a spin there. And iirc, yeah, there's a couple of multi-monitor related APIs you'll want to use.
You indeed need some multi-monitor fixing, as expected I can't drag your window to my second desktop :). Also, it doesn't respect/snap-to the taskbar.
Yeah it doesn't stick to the task-bar. That's by design. It sticks to the bottom of the screen. Um about the multi monitor fixing, I am going to have to read more about it and I think it is going to be really difficult since I don't have multiple monitors :(
yup i've been planning to add in multi monitor support for one of my tools... bit tricky considering i haven't got the hardware...
though i guess f0dder might be a good guinea pig hehe :)
though i guess f0dder might be a good guinea pig hehe :)