2016-11-25 64 views
-1

程序編譯良好,但無法創建主窗口。具體而言,CreateWindowEx失敗並打印「無法創建窗口」。無法使用Windows API和x86彙編創建主窗口

會有人碰巧知道我在做什麼錯嗎?我幾乎完全遵循Kip Irvine關於裝配的書,但似乎我錯過了一些東西。

編輯:我更新了基於建議的代碼。現在程序無法註冊窗口類,具體錯誤是「參數不正確」。我查看了我的WNDCLASSEX結構的參數,並沒有任何錯誤。

編輯2:我從WNDCLASSRegisterClass刪除了「Ex」,現在窗口顯示並正常工作。所以我想這是一種奇怪的重新定義或masm32rt庫中的結構和函數的不一致?

INCLUDE \masm32\include\masm32rt.inc 

.data 
windowName BYTE "ASM Windows App",0 
className BYTE "ASMWin",0 
MainWinClass WNDCLASSEX <NULL,CS_HREDRAW + CS_VREDRAW,WinProc,NULL,NULL,NULL,NULL,NULL,COLOR_WINDOW+1,NULL,className,NULL> 
windowHandle DWORD ? 
hInstance DWORD ? 

.code 
WinMain PROC 

    ; Get a handle to the current process. 
    INVOKE GetModuleHandle, NULL 
    mov hInstance, eax 
    mov MainWinClass.hInstance, eax 

    ; Check if the handle was received. 
    .IF eax == 0 
     pushad 
     print "Failed to get handle on current process" 
     popad 
     call ErrorHandler 
     jmp ExitProgram 
    .ENDIF 

    ; Load the program's icon and cursor. 
    INVOKE LoadIcon, NULL, IDI_APPLICATION 
    mov MainWinClass.hIcon, eax 
    INVOKE LoadCursor, NULL, IDC_ARROW 
    mov MainWinClass.hCursor, eax 

    ; Create the window class. 
    INVOKE RegisterClassEx, ADDR MainWinClass 

    ; Check if the class was registered. 
    .IF eax == 0 
     pushad 
     print "Failed to register class." 
     popad 
     call ErrorHandler 
     jmp ExitProgram 
    .ENDIF 

    ; Create the window. 
    INVOKE CreateWindowEx, 0, ADDR className, ADDR windowName, WS_VISIBLE, 
    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 
    NULL, NULL, hInstance, NULL 

    ; Check if window was created successfully. 
    .IF eax == 0 
     pushad 
     print "Failed to create window" 
     popad 
     call ErrorHandler 
     jmp ExitProgram 
    .ENDIF 

    ; Save the window handle and use it to show the window. 
    mov windowHandle, eax 
    INVOKE ShowWindow, windowHandle, SW_SHOW 
    INVOKE UpdateWindow, windowHandle 

    ; Message Loop 
    ;MessageLoop: 
    ; INVOKE GetMessage, ADDR msg, NULL, NULL, NULL 
    ; INVOKE DispatchMessage, ADDR msg 
    ; jmp MessageLoop 

ExitProgram: 
    ;CALL ReadChar 
    INVOKE ExitProcess, 0 
WinMain ENDP 

; Window Procedure 
WinProc PROC, 
    hWnd:DWORD, localMsg:DWORD, wParam:DWORD, lParam:DWORD 
    mov eax, localMsg 

    .IF eax == WM_CREATE 
     ;call WriteString 
     jmp WinProcExit 
    .ELSEIF eax == WM_CLOSE 
     ;call WriteString 
     jmp WinProcExit 
    .ELSE 
     ;call WriteString 
     INVOKE DefWindowProc, hWnd, localMsg, wParam, lParam 
     jmp WinProcExit 
    .ENDIF 

WinProcExit: 
    ret 
WinProc ENDP 

ErrorHandler PROC 
.data 
pErrorMsg DWORD ? 
messageID DWORD ? 
.code 
    INVOKE GetLastError 
    mov messageID, eax 

    ; Get the corresponding message string. 
    INVOKE FormatMessage, FORMAT_MESSAGE_ALLOCATE_BUFFER + \ 
    FORMAT_MESSAGE_FROM_SYSTEM,NULL,messageID,NULL, 
    ADDR pErrorMsg,NULL,NULL 

    ; Display the error message. 
    INVOKE MessageBox, NULL, pErrorMsg, NULL, 
    MB_ICONERROR+MB_OK 

    ; Free the error message string. 
    INVOKE LocalFree, pErrorMsg 

    ret 
ErrorHandler ENDP 
END WinMain 
+1

你是什麼意思,它沒有創建主窗口? 「CreateWindowEx」失敗,程序打印「無法創建窗口」,或者不打印任何內容,也沒有窗口出現? –

+0

@RossRidge CreateWindowEx失敗並打印「無法創建窗口」。我會確保澄清這一點。 – Artekis

+1

你忘了調用DefWindowProc。 –

回答

1

WNDCLASSEX要求設置WNDCLASSEX.cbSize。我犯的錯誤是我認爲它可能是NULL。

所以我加了這段代碼註冊上課前:

; Initializing other parameters of the window class. 
mov eax, SIZEOF MainWinClass 
mov MainWinClass.cbSize, eax 

此外,沿側使用的Windows API的用戶界面部分的一些功能時硤歐文的功能會導致錯誤。我不確定爲什麼會發生這種情況,但可能會發生一些寄存器值發生變化。

+1

請注意,對於具有'cbSize'成員的所有*** WinAPI結構,這將是正確的。在調用函數前請檢查在線的MSDN文檔。 –

+0

如果您還沒有設置小圖標,則使用Ex功能毫無意義。 – Anders