Я сделал окошка в котором изменеие размера производится с помощью некого элемента окна который на на left mouse down шлет WM_NCLBUTTONDOWN к HTTOPLEFT, т.е. после нажатия на этот элемент начинается изменеие размера окна Код (Text): void OnLBDown(...) { PostMessage(WM_NCLBUTTONDOWN, HTTOPLEFT, NULL); } Все работает просто замечательно, но я не могу избавится от бордюра окна. Окно создается через CreateWindow с параметром (WS_THICKFRAME или WS_DLGFRAME) и окружено тонким бордюром. Если создать окно без WS_THICKFRAME бордюр исчезает, но окно перестает быть resizable и не меняет своего размера на PostMessage(WM_NCLBUTTONDOWN, HTTOPLEFT, NULL); Как бы сесть на елку не уколов попу?
Хммм, в принципе можно, только не совсем понятно когда убирать WS_THICKFRAME. Еще немного раздражает этот бордюр который появляется во время изменения размера. Вот сделать бы его невидимым ...
elimli Форум, конечно, asm - овский, но в Delphi можно это сделать без труда. 1) Создаешь форму со стилем fsNone (ни бордюра, ни заголовка) 2) Изменяешь размер: Form1.Width := newWidth; Скорее всего это можно сделать и в Borland C, а вот как на чистом WinAPI ? Может посмотришь в их сорцы и по ним поймешь ?
Надо просто отвечать на сообщение WM_NCHITTEST. Никаких стилей и всё работает на ура. http://msdn2.microsoft.com/en-us/library/ms645618.aspx
AsmGuru62 Я попробовал в оконной ф-ии просто отбрасывать (retrun 0) WM_NCHITTEST. Окно перстаэт реагировать на мышь, но бордюр на месте
AsmGuru62 >Надо просто отвечать на сообщение WM_NCHITTEST. Никаких стилей и всё работает на ура. Не уверен, что с WM_NCHITTEST получится проще, чем без WM_NCHITTEST: собственная разметка периметра окна наподобие HT(LEFT/TOP/RIGHT/BOTTOM), на WM_SETCURSOR - SetCursor(LoadCursor), на WM_LBUTTONDOWN - DefWindowProc(WM_SYSCOMMAND,SC_SIZE+), - и вот вам эмуляция WS_THICKFRAME, с положенными краевыми курсорами, но без бордюра.
>эмуляция WS_THICKFRAME, с положенными краевыми курсорами, но без бордюра. Пример (сразу и для top-level, и для child): Код (Text): .data _main db "SizeBoxToo",0 _child db "Static",0 .data? .code QuasiHitTest proc hWnd:HWND local pt:POINT local rt:RECT invoke GetCursorPos,addr pt invoke GetWindowRect,hWnd,addr rt xor eax,eax mov ecx,pt.x cmp ecx,rt.left jl @ret cmp ecx,rt.right jg @ret mov ecx,pt.y cmp ecx,rt.top jl @ret cmp ecx,rt.bottom jg @ret mov eax,3 mov ecx,rt.right sub ecx,4 cmp pt.x,ecx jge @f dec eax mov ecx,rt.left add ecx,4 cmp pt.x,ecx jge @f dec eax @@: mov edx,3 mov ecx,rt.bottom sub ecx,4 cmp pt.y,ecx jge @f dec edx mov ecx,rt.top add ecx,4 cmp pt.y,ecx jge @f dec edx @@: shl edx,1 mov ecx,edx shl edx,2 add edx,ecx ; 10*edx add eax,edx @ret: ret QuasiHitTest endp WndProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM mov eax,uMsg .if eax==WM_DESTROY invoke PostQuitMessage,0 .elseif eax==WM_SETCURSOR invoke QuasiHitTest,hWnd .if eax==11 || eax==33 mov eax,32642 ; \ .elseif eax==31 || eax==13 mov eax,32643 ; / .elseif eax==21 || eax==23 mov eax,32644 ; - .elseif eax==12 || eax==32 mov eax,32645 ; | ; .elseif eax==22 ; mov eax,32649 .else mov eax,32512 .endif invoke LoadCursor,0,eax invoke SetCursor,eax .elseif eax==WM_LBUTTONDOWN invoke QuasiHitTest,hWnd ; quasi: .if eax==21 ; HTLEFT mov eax,SC_SIZE+1 .elseif eax==23 ; HTRIGHT mov eax,SC_SIZE+2 .elseif eax==12 ; HTTOP mov eax,SC_SIZE+3 .elseif eax==11 ; HTTOPLEFT mov eax,SC_SIZE+4 .elseif eax==13 ; HTTOPRIGHT mov eax,SC_SIZE+5 .elseif eax==32 ; HTBOTTOM mov eax,SC_SIZE+6 .elseif eax==31 ; HTBOTTOMLEFT mov eax,SC_SIZE+7 .elseif eax==33 ; HTBOTTOMRIGHT mov eax,SC_SIZE+8 .elseif eax==22 ; HTCLIENT (HTCAPTION) mov eax,SC_MOVE+1 .endif jmp @f .elseif eax==WM_RBUTTONUP mov eax,SC_CLOSE @@: mov wParam,eax mov uMsg,WM_SYSCOMMAND jmp @f .else @@: invoke GetWindowLong,hWnd,GWL_USERDATA push lParam push wParam push uMsg push hWnd .if eax==0 call DefWindowProc .else push eax call CallWindowProc .endif jmp @f .endif xor eax,eax @@: ret WndProc endp WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD local wc:WNDCLASSEX local msg:MSG local hWnd:HWND mov wc.cbSize,sizeof WNDCLASSEX mov wc.style,CS_DBLCLKS mov wc.lpfnWndProc, offset WndProc mov wc.cbClsExtra,0 mov wc.cbWndExtra,0 push hInst pop wc.hInstance mov wc.hbrBackground,COLOR_WINDOW+1 mov wc.lpszMenuName,0 mov wc.lpszClassName,offset _main invoke LoadIcon,0,IDI_APPLICATION mov wc.hIcon,eax mov wc.hIconSm,eax invoke LoadCursor,0,IDC_ARROW mov wc.hCursor,eax invoke RegisterClassEx,addr wc invoke CreateWindowEx,WS_EX_TOPMOST,offset _main,offset _main,WS_POPUP OR WS_SYSMENU OR WS_CLIPCHILDREN OR WS_MINIMIZEBOX,100,100,400,200,0,0,hInst,0 mov hWnd,eax invoke ShowWindow,hWnd,CmdShow invoke UpdateWindow,hWnd invoke CreateWindowEx,0,offset _child,offset _main,WS_CHILD OR WS_VISIBLE OR SS_NOTIFY,100,60,200,80,hWnd,0,hInst,0 mov hWnd,eax invoke SetWindowLong,hWnd,GWL_WNDPROC,offset WndProc invoke SetWindowLong,hWnd,GWL_USERDATA,eax .while TRUE invoke GetMessage,addr msg,0,0,0 .break .if (!eax) invoke TranslateMessage,addr msg invoke DispatchMessage,addr msg .endw mov eax,msg.wParam ret WinMain endp start: invoke GetModuleHandle,0 invoke WinMain,eax,0,0,SW_SHOWDEFAULT invoke ExitProcess,eax end start
kero Ваш код отвечает на WM_SETCURSOR и WM_LBUTTONDOWN, а надо отвечать только на одно сообщение - WM_NCHITTEST. Windows самa установит требуемую функциональность. Все курсоры и прочее.
AsmGuru62 >Ваш код отвечает на WM_SETCURSOR и WM_LBUTTONDOWN, а надо отвечать только на одно сообщение - WM_NCHITTEST. >Windows самa установит требуемую функциональность. Все курсоры и прочее. Было бы интересно взглянуть на ваш код, особливо для случая сплошного HTCLIENT, как в моем примере. P.S. И почему так категорично - "надо" ?
"О WM_NCHITTEST в последний раз" А вот и нет. Далеко не все равно, какое окно долбит WM_NCHITTEST. Код (Text): .const BorderWidth equ 4 CornerLenght equ 20 .data _class db "SizeBoxToo",0 _sysmenu db "+ WS_SYSMENU",0 _static db "Static",0 _edit db "Edit",0 .data? .code HitTest1 proc po:DWORD,mi:DWORD,ma:DWORD mov edx,po xor eax,eax mov ecx,mi cmp edx,ecx jl @f ; 0 inc eax add ecx,BorderWidth cmp edx,ecx jl @f ; 1 inc eax add ecx,CornerLenght-BorderWidth cmp edx,ecx jl @f ; 2 inc eax mov ecx,ma sub ecx,CornerLenght cmp edx,ecx jl @f ; 3 inc eax add ecx,CornerLenght-BorderWidth cmp edx,ecx jl @f ; 4 inc eax add ecx,BorderWidth cmp edx,ecx jl @f ; 5 xor eax,eax ; 0 @@: ret HitTest1 endp HitTest2 proc hWnd:HWND local pt:POINT local rt:RECT invoke GetCursorPos,addr pt invoke GetWindowRect,hWnd,addr rt invoke HitTest1,pt.y,rt.top,rt.bottom push eax invoke HitTest1,pt.x,rt.left,rt.right shl eax,4 pop ecx add eax,ecx ret HitTest2 endp WndProc proc uses ebx hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM local buf[128]:BYTE .if uMsg==WM_DESTROY invoke PostQuitMessage,0 .elseif uMsg==WM_NCHITTEST ; invoke DefWindowProc,hWnd,uMsg,wParam,lParam ; mov ebx,eax invoke HitTest2,hWnd .if eax==13h mov eax,HTLEFT .elseif eax==53h mov eax,HTRIGHT .elseif eax==31h mov eax,HTTOP .elseif eax==11h || eax==21h || eax==12h mov eax,HTTOPLEFT .elseif eax==51h || eax==41h || eax==52h mov eax,HTTOPRIGHT .elseif eax==35h mov eax,HTBOTTOM .elseif eax==15h || eax==14h || eax==25h mov eax,HTBOTTOMLEFT .elseif eax==55h || eax==45h || eax==54h mov eax,HTBOTTOMRIGHT .else mov ecx,eax and eax,0fh and ecx,0f0h .if eax!=0 && ecx!=0 mov eax,HTCAPTION .else ; mov eax,ebx mov eax,HTNOWHERE .endif .endif jmp @f .elseif uMsg==WM_NCLBUTTONDBLCLK invoke GetClassName,hWnd,addr buf,127 lea ebx,buf invoke GetWindowLong,hWnd,GWL_STYLE mov ecx,eax and eax,not WS_SYSMENU .if eax==ecx or eax,WS_SYSMENU mov ebx,offset _sysmenu .endif invoke SetWindowLong,hWnd,GWL_STYLE,eax invoke SetWindowPos,hWnd,0,0,0,0,0,SWP_NOZORDER OR SWP_NOMOVE OR SWP_NOSIZE OR SWP_FRAMECHANGED invoke SetWindowText,hWnd,ebx .else invoke GetWindowLong,hWnd,GWL_USERDATA push lParam push wParam push uMsg push hWnd .if eax==0 call DefWindowProc .else push eax call CallWindowProc .endif jmp @f .endif xor eax,eax @@: ret WndProc endp WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD local wc:WNDCLASSEX local msg:MSG local hWnd:HWND local hWin:HWND mov wc.cbSize,sizeof WNDCLASSEX mov wc.style,CS_DBLCLKS mov wc.lpfnWndProc, offset WndProc mov wc.cbClsExtra,0 mov wc.cbWndExtra,0 push hInst pop wc.hInstance mov wc.hbrBackground,COLOR_WINDOW+1 mov wc.lpszMenuName,0 mov wc.lpszClassName,offset _class invoke LoadIcon,0,IDI_APPLICATION mov wc.hIcon,eax mov wc.hIconSm,eax invoke LoadCursor,0,IDC_HAND mov wc.hCursor,eax invoke RegisterClassEx,addr wc invoke CreateWindowEx,WS_EX_TOPMOST,offset _class,offset _class,WS_POPUP OR WS_CLIPCHILDREN,100,100,300,320,0,0,hInst,0 mov hWnd,eax invoke ShowWindow,hWnd,CmdShow invoke UpdateWindow,hWnd invoke CreateWindowEx,0,offset _static,offset _static,WS_CHILD OR WS_VISIBLE OR WS_CLIPSIBLINGS OR SS_NOTIFY,40,40,140,80,hWnd,2000,hInst,0 mov hWin,eax invoke SetWindowLong,hWin,GWL_WNDPROC,offset WndProc invoke SetWindowLong,hWin,GWL_USERDATA,eax invoke CreateWindowEx,0,offset _edit,offset _edit,WS_CHILD OR WS_VISIBLE OR WS_CLIPSIBLINGS OR ES_READONLY,40,180,140,80,hWnd,3000,hInst,0 mov hWin,eax invoke SetWindowLong,hWin,GWL_WNDPROC,offset WndProc invoke SetWindowLong,hWin,GWL_USERDATA,eax .while TRUE invoke GetMessage,addr msg,0,0,0 .break .if (!eax) invoke TranslateMessage,addr msg invoke DispatchMessage,addr msg .endw mov eax,msg.wParam ret WinMain endp start: invoke GetModuleHandle,0 invoke WinMain,eax,0,0,SW_SHOWDEFAULT invoke ExitProcess,eax end start В этом примере с WM_NCHITTEST представлены три типа окон: простое top-level окно и дочерние Edit и Static. Причем для каждого из этих окон на левый даблклик повешен триггер +/-WS_SYSMENU. Плюс HTCLIENT заменен на HTCAPTION, драгдропа ради. И вот что видим: 1) WS_SYSMENU изгоняет ресайзовые курсоры. 2) WS_SYSMENU гробит ресайзинг top-level окна. 3) Со Static-ом совсем хреново: вообще и не ресайзится, и не драгдропится. А вот в предыдущем примере с WM_SYSCOMMAND все тип-топ.
kero Если переместить child так, чтобы его часть вышла за границу parent, то в тех участках границы где child вышел перестает работать resize parent.
Да, не аккуратно как-то Но легко поправить: Код (Text): .const BorderWidth equ 4 CornerLenght equ 20 .data _class db "SizeBoxToo",0 _static db "Static",0 _edit db "Edit",0 .data? hwnd dd ? .code HitTest1 proc po:DWORD,mi:DWORD,ma:DWORD mov edx,po xor eax,eax mov ecx,mi cmp edx,ecx jl @f ; 0 inc eax add ecx,BorderWidth cmp edx,ecx jl @f ; 1 inc eax add ecx,CornerLenght-BorderWidth cmp edx,ecx jl @f ; 2 inc eax mov ecx,ma sub ecx,CornerLenght cmp edx,ecx jl @f ; 3 inc eax add ecx,CornerLenght-BorderWidth cmp edx,ecx jl @f ; 4 inc eax add ecx,BorderWidth cmp edx,ecx jl @f ; 5 xor eax,eax ; 0 @@: ret HitTest1 endp HitTest2 proc hWnd:HWND local pt:POINT local rt:RECT invoke GetCursorPos,addr pt invoke GetWindowRect,hWnd,addr rt invoke HitTest1,pt.y,rt.top,rt.bottom push eax invoke HitTest1,pt.x,rt.left,rt.right shl eax,4 pop ecx add eax,ecx ret HitTest2 endp WndProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM .if uMsg==WM_DESTROY invoke PostQuitMessage,0 .elseif uMsg==WM_NCHITTEST invoke HitTest2,hwnd mov cl,al and al,0fh and cl,0f0h mov edx,hWnd .if edx!=hwnd && (al==1 || al==5 || cl==10h || cl==50h) mov eax,HTTRANSPARENT .else invoke DefWindowProc,hWnd,uMsg,wParam,lParam .endif jmp @f .elseif uMsg==WM_SETCURSOR invoke HitTest2,hWnd .if eax==11h || eax==12h || eax==21h || eax==55h || eax==45h || eax==54h mov eax,IDC_SIZENWSE ; \ ; 32642 .elseif eax==15h || eax==14h || eax==25h || eax==51h || eax==41h || eax==52h mov eax,IDC_SIZENESW ; / ; 32643 .elseif eax==13h || eax==53h mov eax,IDC_SIZEWE ; - ; 32644 .elseif eax==31h || eax==35h mov eax,IDC_SIZENS ; | ; 32645 .else mov eax,IDC_ARROW ; 32512 .endif invoke LoadCursor,0,eax invoke SetCursor,eax .elseif uMsg==WM_LBUTTONDOWN invoke HitTest2,hWnd .if eax==13h mov eax,SC_SIZE or WMSZ_LEFT ; or 1 .elseif eax==53h mov eax,SC_SIZE or WMSZ_RIGHT ; or 2 .elseif eax==31h mov eax,SC_SIZE or WMSZ_TOP ; or 3 .elseif eax==11h || eax==21h || eax==12h mov eax,SC_SIZE or WMSZ_TOPLEFT ; or 4 .elseif eax==51h || eax==41h || eax==52h mov eax,SC_SIZE or WMSZ_TOPRIGHT ; or 5 .elseif eax==35h mov eax,SC_SIZE or WMSZ_BOTTOM ; or 6 .elseif eax==15h || eax==14h || eax==25h mov eax,SC_SIZE OR WMSZ_BOTTOMLEFT ; or 7 .elseif eax==55h || eax==45h || eax==54h mov eax,SC_SIZE or WMSZ_BOTTOMRIGHT ; or 8 .else ; mov eax,SC_SIZE or 9 mov eax,SC_MOVE or 1 ; SC_MOVE or 2 ; ... .endif mov wParam,eax mov uMsg,WM_SYSCOMMAND ; invoke ReleaseCapture jmp @@@ .else @@@: invoke GetWindowLong,hWnd,GWL_USERDATA push lParam push wParam push uMsg push hWnd .if eax==0 call DefWindowProc .else push eax call CallWindowProc .endif jmp @f .endif xor eax,eax @@: ret WndProc endp WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD local wc:WNDCLASSEX local msg:MSG local hWnd:HWND mov wc.cbSize,sizeof WNDCLASSEX mov wc.style,CS_DBLCLKS mov wc.lpfnWndProc, offset WndProc mov wc.cbClsExtra,0 mov wc.cbWndExtra,0 push hInst pop wc.hInstance mov wc.hbrBackground,COLOR_WINDOW+1 mov wc.lpszMenuName,0 mov wc.lpszClassName,offset _class invoke LoadIcon,0,IDI_APPLICATION mov wc.hIcon,eax mov wc.hIconSm,eax invoke LoadCursor,0,IDC_HAND mov wc.hCursor,eax invoke RegisterClassEx,addr wc invoke CreateWindowEx,WS_EX_TOPMOST,offset _class,offset _class,WS_POPUP OR WS_CLIPCHILDREN OR WS_SYSMENU,100,100,300,320,0,0,hInst,0 mov hwnd,eax invoke ShowWindow,hwnd,CmdShow invoke UpdateWindow,hwnd invoke CreateWindowEx,0,offset _static,offset _static,WS_CHILD OR WS_VISIBLE OR WS_CLIPSIBLINGS OR SS_NOTIFY,40,40,140,80,hwnd,2000,hInst,0 mov hWnd,eax invoke SetWindowLong,hWnd,GWL_WNDPROC,offset WndProc invoke SetWindowLong,hWnd,GWL_USERDATA,eax invoke CreateWindowEx,0,offset _edit,offset _edit,WS_CHILD OR WS_VISIBLE OR WS_CLIPSIBLINGS OR ES_READONLY,40,180,140,80,hwnd,3000,hInst,0 mov hWnd,eax invoke SetWindowLong,hWnd,GWL_WNDPROC,offset WndProc invoke SetWindowLong,hWnd,GWL_USERDATA,eax .while TRUE invoke GetMessage,addr msg,0,0,0 .break .if (!eax) invoke TranslateMessage,addr msg invoke DispatchMessage,addr msg .endw mov eax,msg.wParam ret WinMain endp start: invoke GetModuleHandle,0 invoke WinMain,eax,0,0,SW_SHOWDEFAULT invoke ExitProcess,eax end start
WM_NCHITTEST-less Оказывается, слова AsmGuru62 - - чистая правда, если вместо WM_NCHITTEST читать WM_SETCURSOR Код (Text): .const BorderWidth equ 4 CornerLenght equ 20 .data _class db "SizeBoxToo",0 _static db "Static",0 .data? hwnd dd ? .code HitTest1 proc po:DWORD,mi:DWORD,ma:DWORD mov edx,po xor eax,eax mov ecx,mi cmp edx,ecx jl @f ; 0 inc eax add ecx,BorderWidth cmp edx,ecx jl @f ; 1 inc eax add ecx,CornerLenght-BorderWidth cmp edx,ecx jl @f ; 2 inc eax mov ecx,ma sub ecx,CornerLenght cmp edx,ecx jl @f ; 3 inc eax add ecx,CornerLenght-BorderWidth cmp edx,ecx jl @f ; 4 inc eax add ecx,BorderWidth cmp edx,ecx jl @f ; 5 xor eax,eax ; 0 @@: ret HitTest1 endp HitTest2 proc hWnd:HWND local pt:POINT local rt:RECT invoke GetCursorPos,addr pt invoke GetWindowRect,hWnd,addr rt invoke HitTest1,pt.y,rt.top,rt.bottom push eax invoke HitTest1,pt.x,rt.left,rt.right shl eax,4 pop ecx add eax,ecx ret HitTest2 endp WndProc proc hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM .if uMsg==WM_DESTROY invoke PostQuitMessage,0 .elseif uMsg==WM_SETCURSOR invoke HitTest2,hwnd mov cl,al and al,0fh and cl,0f0h mov edx,hWnd .if edx!=hwnd && (al==1 || al==5 || cl==10h || cl==50h) mov edx,hwnd mov hWnd,edx .endif invoke HitTest2,hWnd mov ecx,lParam mov edx,ecx shr edx,16 .if dx==WM_MOUSEMOVE .if eax==11h || eax==12h || eax==21h || eax==55h || eax==45h || eax==54h mov eax,IDC_SIZENWSE ; \ ; 32642 .elseif eax==15h || eax==14h || eax==25h || eax==51h || eax==41h || eax==52h mov eax,IDC_SIZENESW ; / ; 32643 .elseif eax==13h || eax==53h mov eax,IDC_SIZEWE ; - ; 32644 .elseif eax==31h || eax==35h mov eax,IDC_SIZENS ; | ; 32645 .else mov eax,IDC_ARROW ; 32512 .endif invoke LoadCursor,0,eax invoke SetCursor,eax .elseif dx==WM_LBUTTONDOWN .if eax==13h mov eax,SC_SIZE or WMSZ_LEFT ; or 1 .elseif eax==53h mov eax,SC_SIZE or WMSZ_RIGHT ; or 2 .elseif eax==31h mov eax,SC_SIZE or WMSZ_TOP ; or 3 .elseif eax==11h || eax==21h || eax==12h mov eax,SC_SIZE or WMSZ_TOPLEFT ; or 4 .elseif eax==51h || eax==41h || eax==52h mov eax,SC_SIZE or WMSZ_TOPRIGHT ; or 5 .elseif eax==35h mov eax,SC_SIZE or WMSZ_BOTTOM ; or 6 .elseif eax==15h || eax==14h || eax==25h mov eax,SC_SIZE or WMSZ_BOTTOMLEFT ; or 7 .elseif eax==55h || eax==45h || eax==54h mov eax,SC_SIZE or WMSZ_BOTTOMRIGHT ; or 8 .else mov eax,SC_SIZE or 9 ; mov eax,SC_MOVE or 1 ; mov eax,SC_MOVE or 2 .endif mov wParam,eax mov uMsg,WM_SYSCOMMAND jmp @f .else jmp @f .endif .else @@: invoke GetWindowLong,hWnd,GWL_USERDATA push lParam push wParam push uMsg push hWnd .if eax==0 call DefWindowProc .else push eax call CallWindowProc .endif jmp @f .endif xor eax,eax @@: ret WndProc endp SubClass proc hWnd:HWND invoke SetWindowLong,hWnd,GWL_WNDPROC,offset WndProc invoke SetWindowLong,hWnd,GWL_USERDATA,eax ret SubClass endp WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD local wc:WNDCLASSEX local msg:MSG mov wc.cbSize,sizeof WNDCLASSEX mov wc.style,CS_DBLCLKS mov wc.lpfnWndProc, offset WndProc mov wc.cbClsExtra,0 mov wc.cbWndExtra,0 push hInst pop wc.hInstance mov wc.hbrBackground,COLOR_WINDOW+1 mov wc.lpszMenuName,0 mov wc.lpszClassName,offset _class invoke LoadIcon,0,IDI_APPLICATION mov wc.hIcon,eax mov wc.hIconSm,eax invoke LoadCursor,0,IDC_HAND mov wc.hCursor,eax invoke RegisterClassEx,addr wc invoke CreateWindowEx,WS_EX_TOPMOST,offset _class,offset _class,WS_POPUP OR WS_CLIPCHILDREN OR WS_SYSMENU,100,100,310,370,0,0,hInst,0 mov hwnd,eax invoke ShowWindow,hwnd,CmdShow invoke UpdateWindow,hwnd invoke CreateWindowEx,0,offset _class,offset _class, WS_CHILD OR WS_VISIBLE OR WS_CLIPSIBLINGS OR WS_CLIPCHILDREN OR WS_SYSMENU OR WS_CAPTION,40,160,210,160,hwnd,2000,hInst,0 invoke CreateWindowEx,0,offset _static,offset _static,WS_CHILD OR WS_VISIBLE OR WS_CLIPSIBLINGS OR SS_NOTIFY, 20,20,140,80,eax,2001,hInst,0 invoke SubClass,eax invoke CreateWindowEx,0,offset _static,offset _static,WS_CHILD OR WS_VISIBLE OR WS_CLIPSIBLINGS OR SS_NOTIFY,40,40,140,80,hwnd,2002,hInst,0 invoke SubClass,eax .while TRUE invoke GetMessage,addr msg,0,0,0 .break .if (!eax) invoke TranslateMessage,addr msg invoke DispatchMessage,addr msg .endw mov eax,msg.wParam ret WinMain endp start: invoke GetModuleHandle,0 invoke WinMain,eax,0,0,SW_SHOWDEFAULT invoke ExitProcess,eax end start Между прочим, 1) драгдроп поддерживается недокументированной константой SC_SIZE+9, поскольку SC_MOVE+1/SC_MOVE+2 в этом примере почему-то не работают, 2) а поправка q_q реализована иначе, чем в предыдущем примере.