2016-11-25 3 views
-1

プログラムは正常にコンパイルされますが、メインウィンドウの作成に失敗します。具体的には、CreateWindowExが失敗し、「ウィンドウの作成に失敗しました」と表示されます。Windows APIとx86アセンブリを使用したメインウィンドウの作成に失敗しました

私が間違っていることを知っている人は誰ですか?私はアセンブリについてのKip Irvineの本をほぼ正確に追っていますが、何かが欠けているようです。

EDIT:推奨事項に基づいてコードを更新しました。今度はプログラムがウィンドウクラスを登録するのに失敗し、特定のエラーは "パラメータが間違っている"ということです。私は私のWNDCLASSEX構造体のパラメータを見て、何か間違ったことはできませんでした。

EDIT2: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

関連する問題