;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming 2nd Edition>
; by 羅雲彬, http://asm.yeah.net
; change by 小甲魚, http://www.fishc.com
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; FirstWindow.asm
; 窗口程序的模板代碼
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 使用 nmake 或下列命令進行編譯和鏈接:
; ml /c /coff FirstWindow.asm
; Link /subsystem:windows FirstWindow.obj
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat,stdcall
option casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定義
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include gdi32.inc
includelib gdi32.lib
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
include shell32.inc
includelib shell32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 數據段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hInstance dd
?
hWinMain dd
?
.const
szClassName db'MyClass',0
szCaptionMain db'My first Window !',0
szText db
'Welcome to fishc.com!',0
szOpen db
'open', 0
szURL db
'http://www.fishc.com',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代碼段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 窗口過程
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcWinMain procuses ebx edi esi hWnd,uMsg,wParam,lParam
local @stPs:PAINTSTRUCT
local @stRect:RECT
local @hDc
local @hBrush
mov eax,uMsg
;********************************************************************
.if eax ==WM_PAINT
invoke
BeginPaint,hWnd,addr @stPs
mov @hDc,eax
invoke
GetClientRect,hWnd,addr @stRect
invoke
DrawText,@hDc,addr szText,-1,\
addr @stRect,\
DT_SINGLELINE or DT_CENTER or DT_VCENTER
invoke
EndPaint,hWnd,addr @stPs
;********************************************************************
.elseif
eax == WM_CLOSE
invoke
DestroyWindow,hWinMain
invoke
PostQuitMessage,NULL
;********************************************************************
.elseif eax == WM_NCPAINT
invoke
DefWindowProc,hWnd,uMsg,wParam,lParam
invoke
ShellExecute, NULL, offset szOpen,\
offset szURL, NULL, NULL, SW_SHOWNORMAL
;********************************************************************
.else
invoke
DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.endif
;********************************************************************
xor eax,eax
ret
_ProcWinMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_WinMain proc
local @stWndClass:WNDCLASSEX
local @stMsg:MSG
invoke
GetModuleHandle,NULL
mov hInstance,eax
invoke
RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
;********************************************************************
; 註冊窗口類
;********************************************************************
invoke
LoadCursor,0,IDC_ARROW
mov @stWndClass.hCursor,eax
push hInstance ; 注意這種拷貝的方法,以後會常碰到的
pop @stWndClass.hInstance ; 思考:爲什麼不用mov @stWndClass.hInstance, hInstance
mov @stWndClass.cbSize,sizeof WNDCLASSEX
mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW
mov @stWndClass.lpfnWndProc,offset _ProcWinMain
mov @stWndClass.hbrBackground,COLOR_WINDOW + 1
mov @stWndClass.lpszClassName,offset szClassName
invoke
RegisterClassEx,addr @stWndClass
;********************************************************************
; 建立並顯示窗口
;********************************************************************
invoke
CreateWindowEx,WS_EX_CLIENTEDGE,offset szClassName,offset szCaptionMain,\
WS_OVERLAPPEDWINDOW,\
100,100,600,400,\
NULL,NULL,hInstance,NULL
mov hWinMain,eax
invoke
ShowWindow,hWinMain,SW_SHOWNORMAL
invoke
UpdateWindow,hWinMain
;********************************************************************
; 消息循環
;********************************************************************
.while
TRUE
invoke
GetMessage,addr @stMsg,NULL,0,0
.break
.if eax == 0
invoke
TranslateMessage,addr @stMsg
invoke
DispatchMessage,addr @stMsg
.endw
ret
_WinMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
call _WinMain
invoke
ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
WM_NCPAINT
當窗體框架(非客戶區)要被重畫時,WM_NCPAINT消息產生
窗體可用一個WindowProc函數接收這個消息
LRESULT CALLBACK WindowProc(
HWND hwnd, // 窗體句柄
UINT uMsg, // WM_NCPAINT
WPARAMwParam, //處理窗體更新區域 (HRGN)
LPARAMlParam //不用
);
參數
wParam
處理窗體更新區域,對窗體來說缺省更新的部分區域是框架。當wParam設爲1時,整個窗體將得到更新。
返回值
如果應用這個消息就返回零
附言:
DefWindowProc函數畫窗體框架,可以攔截這條WM_NCPAINT消息
並畫自己特有風格的窗體框架。剪切區域總是直角矩形,即使窗體的框架
被改變。
wParam可以傳給GetDCEx函數。看下面例子
case WM_NCPAINT:
{
HDC hdc;
hdc = GetDCEx(hwnd, (HRGN)wParam, DCX_WINDOW|DCX_INTERSECTRGN);
// 進入設備場景畫
ReleaseDC(hwnd, hdc);
}
WinAPI: ShellExecute - 打開外部程序或文件
ShellExecute( hWnd: HWND; {指定父窗口句柄} Operation: PChar; {指定動作, 譬如: open、print} FileName: PChar; {指定要打開的文件或程序} Parameters: PChar; {給要打開的程序指定參數; 如果打開的是文件這裏應該是 nil} Directory: PChar; {缺省目錄} ShowCmd: Integer {打開選項} ): HINST; {執行成功會返回應用程序句柄; 如果這個值 <= 32, 表示執行錯誤} //返回值可能的錯誤有: = 0 {內存不足} ERROR_FILE_NOT_FOUND = 2; {文件名錯誤} ERROR_PATH_NOT_FOUND = 3; {路徑名錯誤} ERROR_BAD_FORMAT = 11; {EXE 文件無效} SE_ERR_SHARE = 26; {發生共享錯誤} SE_ERR_ASSOCINCOMPLETE = 27; {文件名不完全或無效} SE_ERR_DDETIMEOUT = 28; {超時} SE_ERR_DDEFAIL = 29; {DDE 事務失敗} SE_ERR_DDEBUSY = 30; {正在處理其他 DDE 事務而不能完成該 DDE 事務} SE_ERR_NOASSOC = 31; {沒有相關聯的應用程序} //ShowCmd 參數可選值: SW_HIDE = 0; {隱藏} SW_SHOWNORMAL = 1; {用最近的大小和位置顯示, 激活} SW_NORMAL = 1; {同 SW_SHOWNORMAL} SW_SHOWMINIMIZED = 2; {最小化, 激活} SW_SHOWMAXIMIZED = 3; {最大化, 激活} SW_MAXIMIZE = 3; {同 SW_SHOWMAXIMIZED} SW_SHOWNOACTIVATE = 4; {用最近的大小和位置顯示, 不激活} SW_SHOW = 5; {同 SW_SHOWNORMAL} SW_MINIMIZE = 6; {最小化, 不激活} SW_SHOWMINNOACTIVE = 7; {同 SW_MINIMIZE} SW_SHOWNA = 8; {同 SW_SHOWNOACTIVATE} SW_RESTORE = 9; {同 SW_SHOWNORMAL} SW_SHOWDEFAULT = 10; {同 SW_SHOWNORMAL} SW_MAX = 10; {同 SW_SHOWNORMAL} //舉例說明更多問題(別忘了 uses ShellAPI;): {譬如用記事本打開一個文件} begin ShellExecute(Handle, 'open', 'notepad.exe', 'C:\WINDOWS\SchedLgU.Txt', nil, SW_SHOWNORMAL); end; {第一個參數是用來當作錯誤提示窗口的父窗口的, 不能是 nil, 可以是 0(也就是桌面窗口)} begin ShellExecute(0, 'open', 'notepad.exe', 'C:\WINDOWS\SchedLgU.Txt', nil, SW_SHOWNORMAL); end; {第二個參數如果是 nil, 也會默認位 open} begin ShellExecute(0, nil, 'notepad.exe', 'C:\WINDOWS\SchedLgU.Txt', nil, SW_SHOWNORMAL); end; {文件路徑可以放在參數五} begin ShellExecute(0, nil, 'notepad.exe', 'SchedLgU.Txt', 'C:\WINDOWS', SW_SHOWNORMAL); end; {把參數三直接指定爲要打開的文件, 文件將用對應默認程序打開; 次數參數四應爲 nil} begin ShellExecute(0, nil, 'SchedLgU.Txt', nil, 'C:\WINDOWS', SW_SHOWNORMAL); end; {如果文件在: 程序目錄/當前目錄/System32/Windows/PATH環境變量中, 參數五也可以 nil} begin ShellExecute(0, nil, 'SchedLgU.Txt', nil, nil, SW_SHOWNORMAL); end; {如果參數三是個文件, 可以用參數二命令打印} begin ShellExecute(0, 'print', 'SchedLgU.Txt', nil, nil, 1); end; {用 IE 打開網頁} begin ShellExecute(Handle, 'open', 'IExplore.EXE', 'about:blank', nil, SW_SHOWNORMAL); end; {用火狐打開網頁} begin ShellExecute(Handle, 'open', 'firefox.exe', 'about:blank', nil, SW_SHOWNORMAL); end; {用默認瀏覽器打開網頁} begin ShellExecute(Handle, 'open', 'Explorer.exe', 'about:blank', nil, SW_SHOWNORMAL); end; {還是用默認瀏覽器打開網頁} begin ShellExecute(0, nil, 'http://del.cnblogs.com', nil, nil, 1); end;