windows10 安裝NASM


在編寫nasm時數字默認為10進制

x86控制台程序

objexe.asm:

; equ 定義常量
STD_OUTPUT_HANDLE EQU -11

; 導入外部符號, Windows API函數,已修飾
extern _GetStdHandle@4              
extern _WriteFile@20
extern _ExitProcess@4

global Start                                    ; 導出符號。 入口點

section .data                                   ; 初始化數據段
 Message        db "hello.", 0Dh, 0Ah           ; 0Dh 0Ah 回車/換行
 MessageLength  EQU $ - Message                 ; $ - Message地址 == Message長度

section .bss                                    ; 未初始化的數據段
 Written        resd 1                          ; 一個dword的大小,4字節,32位

section .text                                   ; 代碼段
Start:
 push  STD_OUTPUT_HANDLE
 call  _GetStdHandle@4				;檢索指定標准設備

 push  0                                        ; 第5個參數
 push  Written                                  ; 第4個參數
 push  MessageLength                            ; 第3個參數
 push  Message                                  ; 第2個參數
 push  EAX                        		; 第1個參數 i/o句柄
 call  _WriteFile@20                            ; 調用函數,將數據寫入指定的文件或輸入/輸出(I/O)設備
 
 push  0
 call  _ExitProcess@4
>nasm -f win32 objexe.asm
>golink /entry:Start /console kernel32.dll user32.dll objexe.obj
>objexe.exe
hello.

x64控制台程序

STD_OUTPUT_HANDLE EQU -11

extern GetStdHandle
extern WriteFile
extern ExitProcess

global Start

section .data
 Message        db "hello x64.", 0Dh, 0Ah
 MessageLength  EQU $-Message

section .bss
; 結構對齊
; 最大成員為8字節
; 該結構應從8整除的內存位置開始,alignb 8確保
; 如果其中有個成員為4字節,那么你要保證接下來的8字節成員自然對齊,那么就需要加padding
; 最后: 總長度要可以被8整除,不能整除就加padding 16/8=2
alignb 8
 StandardHandle resq 1
 Written        resq 1
 
 ; test resd 1 ;4字節成員
 ; padding1 resd 1 ;加padding對齊

section .text
Start:
 sub   RSP, 8                                   ; 將堆棧對齊為16個字節的倍數

 sub   RSP, 32                                  ; 陰影空間32字節
 mov   ECX, STD_OUTPUT_HANDLE
 call  GetStdHandle
 
 mov   qword [REL StandardHandle], RAX
 add   RSP, 32                                  ; 刪除32個字節

 ; 4個參數每個8字節就是32,外加一個堆棧上的就是8字節
 ; 函數在內部會把這些參數放在堆棧,寄存器就那么幾個
 ; 最后+8使堆棧對齊16個字節的倍數 48/16=3  40/16=2.5,能整除就是對齊
 sub   RSP, 32 + 8 + 8                          ; 陰影空間+第5個參數+對齊堆棧
                                                ; to a multiple of 16 bytes
 mov   RCX, qword [REL StandardHandle]          ; 第1個參數
 lea   RDX, [REL Message]                       ; 第2個參數
 mov   R8, MessageLength                        ; 第3個參數
 lea   R9, [REL Written]                        ; 第4個參數
 mov   qword [RSP + 32], 0                   	; 第5個參數
 call  WriteFile
 add   RSP, 48                                  ; 刪除48個字節

 xor   ECX, ECX									;異或 ECX = 0
 call  ExitProcess
>nasm -f win64 objexe.asm
>golink /entry:Start /console kernel32.dll user32.dll objexe.obj
>objexe.exe
hello x64.

x86 MessageBox

extern MessageBoxA
extern ExitProcess

global Start

section .data
	text db "hello.",0
	title db "title",0
	
section .text
Start:
	; int MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
	push 0x00000001
	push title
	push text
	push 0
	call MessageBoxA
	
	; 如果點擊了取消,就繼續彈
	cmp eax,2
	je Start
	
	; 退出
	push 0
	call ExitProcess
>nasm -f win32 objexe.asm
>golink /entry:Start kernel32.dll user32.dll objexe.obj
>objexe.exe

x64 MessageBox

extern MessageBoxA
extern ExitProcess

global Start

section .data
	text db "hello.",0
	title db "title",0
	
section .text
Start:
	sub rsp, 8
	sub rsp, 32

_msgbox:
	; int MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
	xor ecx,ecx
	lea edx,[text]
	lea r8,[title]
	mov r9,0x01
	call MessageBoxA

	; 如果點擊了取消,就繼續彈
	cmp rax,0x2
	je _msgbox
	
	add rsp, 32

_exit:
	xor ecx,ecx
	call ExitProcess
>nasm -f win64 objexe.asm
>golink /entry:Start kernel32.dll user32.dll objexe.obj
>objexe.exe

x86 基本窗口

WindowWidth         EQU 640
WindowHeight        EQU 480

extern _CreateWindowExA@48
extern _DefWindowProcA@16
extern _DispatchMessageA@4
extern _ExitProcess@4
extern _GetMessageA@16
extern _GetModuleHandleA@4
extern _IsDialogMessageA@8
extern _LoadImageA@24
extern _PostQuitMessage@4
extern _RegisterClassExA@4
extern _ShowWindow@8
extern _TranslateMessage@4
extern _UpdateWindow@4

global Start

section .data
 WindowName db "Basic Window 32", 0
 ClassName  db "Window", 0

section .bss
 hInstance resd 1

section .text
Start:

 ; https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getmodulehandlea
 push  0
 call  _GetModuleHandleA@4
 mov   dword [hInstance], EAX ; 保存返回的模塊句柄

 call  WinMain

.Exit:
 push  0
 call  _ExitProcess@4

WinMain:
 push  EBP
 mov   EBP, ESP
 sub   ESP, 80                                  ; 80個字節的局部變量的空間

; define 指令用於分配存儲空間。它可以用於保留以及初始化一個或多個字節。
; https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-wndclassexa
%define wc                 EBP - 80             ; WNDCLASSEX結構(包含窗口類信息). 48字節
%define wc.cbSize          EBP - 80
%define wc.style           EBP - 76
%define wc.lpfnWndProc     EBP - 72
%define wc.cbClsExtra      EBP - 68
%define wc.cbWndExtra      EBP - 64
%define wc.hInstance       EBP - 60
%define wc.hIcon           EBP - 56
%define wc.hCursor         EBP - 52
%define wc.hbrBackground   EBP - 48
%define wc.lpszMenuName    EBP - 44
%define wc.lpszClassName   EBP - 40
%define wc.hIconSm         EBP - 36

%define msg                EBP - 32             ; MSG結構. 28字節
%define msg.hwnd           EBP - 32             ; 不必拆分每個成員
%define msg.message        EBP - 28             ; 在這種情況下,但它顯示了每個
%define msg.wParam         EBP - 24             ; 成員在堆棧上
%define msg.lParam         EBP - 20
%define msg.time           EBP - 16
%define msg.pt.x           EBP - 12
%define msg.pt.y           EBP - 8

%define hWnd               EBP - 4

 mov   dword [wc.cbSize], 48                    ; [EBP - 80]
 mov   dword [wc.style], 2 | 1 | 2000h  		; [EBP - 76]
 mov   dword [wc.lpfnWndProc], WndProc          ; [EBP - 72]
 mov   dword [wc.cbClsExtra], 0              ; [EBP - 68]
 mov   dword [wc.cbWndExtra], 0              ; [EBP - 64]
 mov   EAX, dword [hInstance]                   ; Global
 mov   dword [wc.hInstance], EAX                ; [EBP - 60]

 ; 加載圖標,光標,動畫光標或位圖
 push  8000h
 push  0
 push  0
 push  1	;加載一個圖標
 push  7F00h	
 push  0
 call  _LoadImageA@24                           ; Large program icon
 mov   dword [wc.hIcon], EAX                    ; [EBP - 56]

 push  8000h
 push  0
 push  0
 push  2	;加載游標
 push  7F00h
 push  0
 call  _LoadImageA@24                           ; Cursor
 mov   dword [wc.hCursor], EAX                  ; [EBP - 52]

 mov   dword [wc.hbrBackground], 5 + 1  ; [EBP - 48]
 mov   dword [wc.lpszMenuName], 0            ; [EBP - 44]
 mov   dword [wc.lpszClassName], ClassName      ; [EBP - 40]

 push  8000h
 push  0
 push  0
 push  1
 push  7F00h
 push  0
 call  _LoadImageA@24                           ; Small program icon
 mov   dword [wc.hIconSm], EAX                  ; [EBP - 36]

 ; 注冊一個窗口類,供以后在對CreateWindow或CreateWindowEx函數的調用中使用
 ;https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerclassexa
 lea   EAX, [wc]                                ; [EBP - 80]
 push  EAX
 call  _RegisterClassExA@4

;創建具有擴展窗口樣式的重疊窗口
;https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexa
 push  0
 push  dword [hInstance]                        ; Global
 push  0
 push  0
 push  WindowHeight
 push  WindowWidth
 push  0	;y
 push  0	;x
 push  0CF0000h		;窗口樣式 https://docs.microsoft.com/en-us/windows/win32/winmsg/window-styles
 push  WindowName                               ; Global
 push  ClassName                                ; Global
 push  2000000h
 call  _CreateWindowExA@48
 mov   dword [hWnd], EAX                        ; [EBP - 4] 新窗口句柄

;設置指定窗口的顯示狀態, 1 激活並顯示一個窗口
 push  1
 push  dword [hWnd]                             ; [EBP - 4]
 call  _ShowWindow@8

 push  dword [hWnd]                             ; [EBP - 4]
 call  _UpdateWindow@4

.MessageLoop:

;從調用線程的消息隊列中檢索消息
 lea   EAX, [msg]                               ; [EBP - 32]
 push  0
 push  0
 push  0
 push  EAX
 call  _GetMessageA@16
 cmp   EAX, 0
 je    .Done

;確定是否將消息用於指定的對話框,如果是,則處理該消息
 lea   EAX, [msg]                               ; [EBP - 32]
 push  EAX
 push  dword [hWnd]                             ; [EBP - 4]
 call  _IsDialogMessageA@8                      ; For keyboard strokes
 cmp   EAX, 0									; 如果消息已處理,則返回值為非零
 jne   .MessageLoop                             ; 跳過TranslateMessage和DispatchMessage

;將虛擬鍵消息轉換為字符消息。字符消息將發布到調用線程的消息隊列中
;以在線程下次調用GetMessage或PeekMessage函數時讀取。
 lea   EAX, [msg]                               ; [EBP - 32]
 push  EAX
 call  _TranslateMessage@4

;將消息調度到窗口過程。它通常用於調度由GetMessage函數檢索的消息
 lea   EAX, [msg]                               ; [EBP - 32]
 push  EAX
 call  _DispatchMessageA@4
 jmp   .MessageLoop

.Done:
 mov   ESP, EBP                                 ; Remove the stack frame
 pop   EBP
 xor   EAX, EAX
 ret

; 回調函數
WndProc:
 push  EBP                                      ; Set up a Stack frame
 mov   EBP, ESP

; 獲取參數
%define hWnd    EBP + 8                         ; Location of the 4 passed parameters from
%define uMsg    EBP + 12                        ; the calling function
%define wParam  EBP + 16                        ; We can now access these parameters by name
%define lParam  EBP + 20

 cmp   dword [uMsg], 2                 ; [EBP + 12]
 je    _WMDESTROY

_DefaultMessage:
 push  dword [lParam]                           ; [EBP + 20]
 push  dword [wParam]                           ; [EBP + 16]
 push  dword [uMsg]                             ; [EBP + 12]
 push  dword [hWnd]                             ; [EBP + 8]
 call  _DefWindowProcA@16

 mov   ESP, EBP                                 ; Remove the stack frame
 pop   EBP
 ret   16                                       ; 內平棧,這就涉及到調用約定,被調用的函數需要處理堆棧

_WMDESTROY:
;向系統指示線程已請求終止(退出)
 push  0
 call  _PostQuitMessage@4

 xor   EAX, EAX                                 ; return 0
 mov   ESP, EBP                                 ; Remove the stack frame
 pop   EBP
 ret   16                                       ; 內平棧
>nasm -f win32 objexe.asm
>golink /entry:Start kernel32.dll user32.dll  objexe.obj
>objexe.exe

x64 基本窗口

                                                ; Basic Window, 64 bit. V1.02
COLOR_WINDOW        EQU 5                       ; Constants
CS_BYTEALIGNWINDOW  EQU 2000h
CS_HREDRAW          EQU 2
CS_VREDRAW          EQU 1
CW_USEDEFAULT       EQU 80000000h
IDC_ARROW           EQU 7F00h
IDI_APPLICATION     EQU 7F00h
IMAGE_CURSOR        EQU 2
IMAGE_ICON          EQU 1
LR_SHARED           EQU 8000h
NULL                EQU 0
SW_SHOWNORMAL       EQU 1
WM_DESTROY          EQU 2
WS_EX_COMPOSITED    EQU 2000000h
WS_OVERLAPPEDWINDOW EQU 0CF0000h

WindowWidth         EQU 640
WindowHeight        EQU 480

extern CreateWindowExA                          ; Import external symbols
extern DefWindowProcA                           ; Windows API functions, not decorated
extern DispatchMessageA
extern ExitProcess
extern GetMessageA
extern GetModuleHandleA
extern IsDialogMessageA
extern LoadImageA
extern PostQuitMessage
extern RegisterClassExA
extern ShowWindow
extern TranslateMessage
extern UpdateWindow

global Start                                    ; Export symbols. The entry point

section .data                                   ; Initialized data segment
 WindowName  db "Basic Window 64", 0
 ClassName   db "Window", 0

section .bss                                    ; Uninitialized data segment
 alignb 8
 hInstance resq 1

section .text                                   ; Code segment
Start:
 sub   RSP, 8                                   ; Align stack pointer to 16 bytes

 ; GetModuleHandleA 只有一個參數為什么還分配32字節的陰影空間
 ; win64函數約定,假定您已經分配了32個字節的堆棧空間來存儲四個參數寄存器
 ; 自己寫的函數可以不用遵守
 sub   RSP, 32                                  ; 32 bytes of shadow space
 xor   ECX, ECX
 call  GetModuleHandleA
 mov   qword [REL hInstance], RAX
 add   RSP, 32                                  ; Remove the 32 bytes

 call  WinMain

.Exit:
 xor   ECX, ECX
 call  ExitProcess

WinMain:
 push  RBP                                      ; Set up a stack frame
 mov   RBP, RSP
 sub   RSP, 136 + 8                             ; 局部變量為136個字節
                                                ; a multiple of 16 (for Windows API functions),
                                                ; the + 8 takes care of this.

%define wc                 RBP - 136            ; WNDCLASSEX structure, 80 bytes
%define wc.cbSize          RBP - 136            ; 4 bytes. Start on an 8 byte boundary
%define wc.style           RBP - 132            ; 4 bytes
%define wc.lpfnWndProc     RBP - 128            ; 8 bytes
%define wc.cbClsExtra      RBP - 120            ; 4 bytes
%define wc.cbWndExtra      RBP - 116            ; 4 bytes
%define wc.hInstance       RBP - 112            ; 8 bytes
%define wc.hIcon           RBP - 104            ; 8 bytes
%define wc.hCursor         RBP - 96             ; 8 bytes
%define wc.hbrBackground   RBP - 88             ; 8 bytes
%define wc.lpszMenuName    RBP - 80             ; 8 bytes
%define wc.lpszClassName   RBP - 72             ; 8 bytes
%define wc.hIconSm         RBP - 64             ; 8 bytes. End on an 8 byte boundary

; msg結構最大成員8字節 總字節數44+4字節的結構對齊=48 48/8=6 
%define msg                RBP - 56             ; MSG structure, 48 bytes
%define msg.hwnd           RBP - 56             ; 8 bytes. Start on an 8 byte boundary
%define msg.message        RBP - 48             ; 4 bytes
%define msg.Padding1       RBP - 44             ; 4字節自然對齊
%define msg.wParam         RBP - 40             ; 8 bytes
%define msg.lParam         RBP - 32             ; 8 bytes
%define msg.time           RBP - 24             ; 4 bytes
%define msg.py.x           RBP - 20             ; 4 bytes
%define msg.pt.y           RBP - 16             ; 4 bytes
%define msg.Padding2       RBP - 12             ; 4字節結構對齊

%define hWnd               RBP - 8              ; 8 bytes

 mov   dword [wc.cbSize], 80                    ; [RBP - 136]
 mov   dword [wc.style], CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW  ; [RBP - 132]
 lea   RAX, [REL WndProc]
 mov   qword [wc.lpfnWndProc], RAX              ; [RBP - 128]
 mov   dword [wc.cbClsExtra], NULL              ; [RBP - 120]
 mov   dword [wc.cbWndExtra], NULL              ; [RBP - 116]
 mov   RAX, qword [REL hInstance]               ; Global
 mov   qword [wc.hInstance], RAX                ; [RBP - 112]

 sub   RSP, 32 + 16                             ; Shadow space + 2 parameters
 xor   ECX, ECX
 mov   EDX, IDI_APPLICATION
 mov   R8D, IMAGE_ICON
 xor   R9D, R9D
 mov   qword [RSP + 4 * 8], NULL
 mov   qword [RSP + 5 * 8], LR_SHARED
 call  LoadImageA                               ; Large program icon
 mov   qword [wc.hIcon], RAX                    ; [RBP - 104]
 add   RSP, 48                                  ; Remove the 48 bytes

 sub   RSP, 32 + 16                             ; Shadow space + 2 parameters
 xor   ECX, ECX
 mov   EDX, IDC_ARROW
 mov   R8D, IMAGE_CURSOR
 xor   R9D, R9D
 mov   qword [RSP + 4 * 8], NULL
 mov   qword [RSP + 5 * 8], LR_SHARED
 call  LoadImageA                               ; Cursor
 mov   qword [wc.hCursor], RAX                  ; [RBP - 96]
 add   RSP, 48                                  ; Remove the 48 bytes

 mov   qword [wc.hbrBackground], COLOR_WINDOW + 1  ; [RBP - 88]
 mov   qword [wc.lpszMenuName], NULL            ; [RBP - 80]
 lea   RAX, [REL ClassName]
 mov   qword [wc.lpszClassName], RAX            ; [RBP - 72]

 sub   RSP, 32 + 16                             ; Shadow space + 2 parameters
 xor   ECX, ECX
 mov   EDX, IDI_APPLICATION
 mov   R8D, IMAGE_ICON
 xor   R9D, R9D
 mov   qword [RSP + 4 * 8], NULL
 mov   qword [RSP + 5 * 8], LR_SHARED
 call  LoadImageA                               ; Small program icon
 mov   qword [wc.hIconSm], RAX                  ; [RBP - 64]
 add   RSP, 48                                  ; Remove the 48 bytes

 sub   RSP, 32                                  ; 32 bytes of shadow space
 lea   RCX, [wc]                                ; [RBP - 136]
 call  RegisterClassExA
 add   RSP, 32                                  ; Remove the 32 bytes

 sub   RSP, 32 + 64                             ; Shadow space + 8 parameters
 mov   ECX, WS_EX_COMPOSITED
 lea   RDX, [REL ClassName]                     ; Global
 lea   R8, [REL WindowName]                     ; Global
 mov   R9D, WS_OVERLAPPEDWINDOW
 mov   dword [RSP + 4 * 8], CW_USEDEFAULT
 mov   dword [RSP + 5 * 8], CW_USEDEFAULT
 mov   dword [RSP + 6 * 8], WindowWidth
 mov   dword [RSP + 7 * 8], WindowHeight
 mov   qword [RSP + 8 * 8], NULL
 mov   qword [RSP + 9 * 8], NULL
 mov   RAX, qword [REL hInstance]               ; Global
 mov   qword [RSP + 10 * 8], RAX
 mov   qword [RSP + 11 * 8], NULL
 call  CreateWindowExA
 mov   qword [hWnd], RAX                        ; [RBP - 8]
 add   RSP, 96                                  ; Remove the 96 bytes

 sub   RSP, 32                                  ; 32 bytes of shadow space
 mov   RCX, qword [hWnd]                        ; [RBP - 8]
 mov   EDX, SW_SHOWNORMAL
 call  ShowWindow
 add   RSP, 32                                  ; Remove the 32 bytes

 sub   RSP, 32                                  ; 32 bytes of shadow space
 mov   RCX, qword [hWnd]                        ; [RBP - 8]
 call  UpdateWindow
 add   RSP, 32                                  ; Remove the 32 bytes

.MessageLoop:
 sub   RSP, 32                                  ; 32 bytes of shadow space
 lea   RCX, [msg]                               ; [RBP - 56]
 xor   EDX, EDX
 xor   R8D, R8D
 xor   R9D, R9D
 call  GetMessageA
 add   RSP, 32                                  ; Remove the 32 bytes
 cmp   RAX, 0
 je    .Done

 sub   RSP, 32                                  ; 32 bytes of shadow space
 mov   RCX, qword [hWnd]                        ; [RBP - 8]
 lea   RDX, [msg]                               ; [RBP - 56]
 call  IsDialogMessageA                         ; For keyboard strokes
 add   RSP, 32                                  ; Remove the 32 bytes
 cmp   RAX, 0
 jne   .MessageLoop                             ; Skip TranslateMessage and DispatchMessageA

 sub   RSP, 32                                  ; 32 bytes of shadow space
 lea   RCX, [msg]                               ; [RBP - 56]
 call  TranslateMessage
 add   RSP, 32                                  ; Remove the 32 bytes

 sub   RSP, 32                                  ; 32 bytes of shadow space
 lea   RCX, [msg]                               ; [RBP - 56]
 call  DispatchMessageA
 add   RSP, 32                                  ; Remove the 32 bytes
 jmp   .MessageLoop

.Done:
 mov   RSP, RBP                                 ; Remove the stack frame
 pop   RBP
 xor   EAX, EAX
 ret

; 回調函數
WndProc:
 push  RBP                                      ; Set up a stack frame
 mov   RBP, RSP

; 獲取陰影空間
; call+上面的push  RBP會導致rsp-16,所以第一個要+16
%define hWnd   RBP + 16                         ; Location of the shadow space setup by
%define uMsg   RBP + 24                         ; the calling function
%define wParam RBP + 32
%define lParam RBP + 40

; 將函數參數放在陰影空間
 mov   qword [hWnd], RCX                        ; Free up RCX RDX R8 R9 by spilling the
 mov   qword [uMsg], RDX                        ; 4 passed parameters to the shadow space
 mov   qword [wParam], R8                       ; We can now access these parameters by name
 mov   qword [lParam], R9

 cmp   qword [uMsg], WM_DESTROY                 ; [RBP + 24]
 je    _WMDESTROY

_DefaultMessage:
 ; DefWindowProcA需要4個參數,4*8=32 32/16=2 能對齊不用手動對齊
 sub   RSP, 32                                  ; 32 bytes of shadow space
 mov   RCX, qword [hWnd]                        ; [RBP + 16]
 mov   RDX, qword [uMsg]                        ; [RBP + 24]
 mov   R8, qword [wParam]                       ; [RBP + 32]
 mov   R9, qword [lParam]                       ; [RBP + 40]
 call  DefWindowProcA
 add   RSP, 32                                  ; Remove the 32 bytes

 mov   RSP, RBP                                 ; Remove the stack frame
 pop   RBP
 ret

_WMDESTROY:
 sub   RSP, 32                                  ; 32 bytes of shadow space
 xor   ECX, ECX
 call  PostQuitMessage
 add   RSP, 32                                  ; Remove the 32 bytes

 xor   EAX, EAX                                 ; WM_DESTROY has been processed, return 0
 mov   RSP, RBP                                 ; Remove the stack frame
 pop   RBP
 ret

x86 基本窗口擴展 看原文

對基本窗口示例的改進:

  • 窗口將在屏幕上居中
  • 客戶區現在將是正確的大小(在調整大小之前)
  • 窗口具有背景色
  • 將創建2個靜態控件。單擊時文本會更改顏色
  • 創建2個編輯控件。Tab鍵可用於更改焦點
  • 靜態和編輯控件的字體從系統默認值更改
  • 窗口上有一個黑色矩形
  • 關閉窗口時顯示退出確認

x64 基本窗口擴展 看原文

對基本窗口示例的改進:

  • 窗口將在屏幕上居中
  • 客戶區現在將是正確的大小(在調整大小之前)
  • 窗口具有背景色
  • 將創建2個靜態控件。單擊時文本會更改顏色
  • 創建2個編輯控件。Tab鍵可用於更改焦點
  • 靜態和編輯控件的字體從系統默認值更改
  • 窗口上有一個黑色矩形
  • 關閉窗口時顯示退出確認


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM