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
Posted on 2008-01-12 23:50:28 by XCHG
Is this more like those "snap-to" windows, ones that ride along a screen edge or something else completely?
Posted on 2008-01-13 00:48:10 by SpooK
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:
Posted on 2008-01-13 01:26:30 by XCHG
handles multiple monitors?
Posted on 2008-01-13 06:15:59 by evlncrn8

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?
Posted on 2008-01-13 06:46:45 by XCHG


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.
Posted on 2008-01-13 08:01:34 by f0dder

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.
Posted on 2008-01-13 11:57:40 by XCHG
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.
Posted on 2008-01-13 12:33:11 by f0dder
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.
Posted on 2008-01-14 06:59:53 by f0dder
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 :(
Posted on 2008-01-14 08:02:45 by XCHG
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 :)
Posted on 2008-01-14 09:14:01 by evlncrn8