2016-11-25 31 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