2016-11-25 5 views
-1

프로그램이 제대로 컴파일되지만 기본 창을 만들지 못합니다. 특히 CreateWindowEx이 실패하고 "창을 만들지 못했습니다."라는 메시지가 인쇄됩니다.Windows API 및 x86 어셈블리를 사용하여 기본 창을 만들지 못했습니다.

내가 뭘 잘못하고 있는지 알 수 있습니까? 나는 조립에 관한 Kip Irvine의 책을 거의 정확하게 따라 가고 있지만, 나는 뭔가를 놓치고있는 것 같다.

편집 : 권장 사항을 기반으로 코드를 업데이트했습니다. 이제 프로그램에서 창 클래스를 등록하지 못하고 "Parameter is incorrect"라는 특정 오류가 발생합니다. 내 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 일 수 있다고 가정했기 때문입니다.

는 그래서 클래스를 등록하기 전에이 코드 조각을 추가 : 측면을 따라 윈도우 API의 사용자 인터페이스 부분의 일부 기능을 사용할 때 또한

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

는 킵 어바인의 기능 오류가 발생합니다. 왜 그런 일이 발생하는지 정확히 알 수는 없지만 일부 레지스터 값이 변경 될 수 있습니다.

+1

이것은 'cbSize' 멤버를 가진 *** 모든 *** WinAPI 구조체에 적용됩니다. 확실하게 함수를 호출하기 전에 온라인 MSDN 설명서를 확인하십시오. –

+0

작은 아이콘도 설정하지 않으면 Ex 기능을 사용하는 것이 의미가 없습니다. – Anders