Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ WIN32对话框引发异常_C++_Winapi_Dialog - Fatal编程技术网

C++ WIN32对话框引发异常

C++ WIN32对话框引发异常,c++,winapi,dialog,C++,Winapi,Dialog,我正在尝试使用Microsoft文档学习win32 api。我已经读到了第4章,我似乎遇到了一个我正在努力调试的问题。“关于”按钮触发的对话框引发异常: practice.exe中0x773BDCFF(ntdll.dll)处引发异常:0xC0000005:访问冲突读取位置0x00905A4C 以下是WndProc的声明和关于回调的声明: static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM l

我正在尝试使用Microsoft文档学习win32 api。我已经读到了第4章,我似乎遇到了一个我正在努力调试的问题。“关于”按钮触发的对话框引发异常:

practice.exe中0x773BDCFF(ntdll.dll)处引发异常:0xC0000005:访问冲突读取位置0x00905A4C

以下是WndProc的声明和关于回调的声明:

static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
static INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK App::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    App* pApp; 
    if (message == WM_CREATE) 
    {
        LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam;
        pApp = (App*)pcs->lpCreateParams; 
        ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, PtrToUlong(pApp));
        return TRUE;
    }
    else
    {
        pApp = reinterpret_cast<App*>(static_cast<LONG_PTR>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA)));
        if (!pApp)
            return DefWindowProc(hWnd, message, wParam, lParam); 
    }

    int wmld, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
    case WM_COMMAND:
    {
        int wmId = LOWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
        case IDM_ABOUT: 
            DialogBox(pApp->getInstance(), MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, pApp->About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }
    break;
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);
        // TODO: Add any drawing code that uses hdc here...
        EndPaint(hWnd, &ps);
    }
    break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Message handler for about box.
INT_PTR CALLBACK App::About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 
{
    UNREFERENCED_PARAMETER(lParam); 
    switch (message) 
    {
        case WM_INITDIALOG: 
            return (INT_PTR)TRUE;

        case WM_COMMAND: 
            if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
            {
                EndDialog(hDlg, LOWORD(wParam));
                return (INT_PTR)TRUE; 
            } 
            break; 
    } 
        return (INT_PTR)FALSE;
以下是实现WndProc和回调的代码:

static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
static INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK App::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    App* pApp; 
    if (message == WM_CREATE) 
    {
        LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam;
        pApp = (App*)pcs->lpCreateParams; 
        ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, PtrToUlong(pApp));
        return TRUE;
    }
    else
    {
        pApp = reinterpret_cast<App*>(static_cast<LONG_PTR>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA)));
        if (!pApp)
            return DefWindowProc(hWnd, message, wParam, lParam); 
    }

    int wmld, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
    case WM_COMMAND:
    {
        int wmId = LOWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
        case IDM_ABOUT: 
            DialogBox(pApp->getInstance(), MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, pApp->About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }
    break;
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);
        // TODO: Add any drawing code that uses hdc here...
        EndPaint(hWnd, &ps);
    }
    break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Message handler for about box.
INT_PTR CALLBACK App::About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 
{
    UNREFERENCED_PARAMETER(lParam); 
    switch (message) 
    {
        case WM_INITDIALOG: 
            return (INT_PTR)TRUE;

        case WM_COMMAND: 
            if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
            {
                EndDialog(hDlg, LOWORD(wParam));
                return (INT_PTR)TRUE; 
            } 
            break; 
    } 
        return (INT_PTR)FALSE;
LRESULT回调应用程序::WndProc(HWND-HWND,UINT消息,WPARAM-WPARAM,LPARAM-LPARAM)
{
App*pApp;
如果(消息==WM_创建)
{
LPCREATESTRUCT pcs=(LPCREATESTRUCT)lpram;
pApp=(应用程序*)pcs->lpCreateParams;
::SetWindowLongPtrW(hWnd、GWLP_用户数据、PtrToUlong(pApp));
返回TRUE;
}
其他的
{
pApp=reinterpret_cast(静态_cast(::GetWindowLongPtrW(hWnd,GWLP_USERDATA));
if(!pApp)
返回DefWindowProc(hWnd、message、wParam、lParam);
}
int wmld,wmEvent;
PAINTSTRUCT-ps;
HDC-HDC;
开关(信息)
{
case WM_命令:
{
int wmId=低ORD(wParam);
//解析菜单选项:
交换机(wmId)
{
案例IDM_关于:
对话框(pApp->getInstance(),MAKEINTRESOURCE(IDD_ABOUTBOX),hWnd,pApp->About);
打破
案例IDM_退出:
窗口(hWnd);
打破
违约:
返回DefWindowProc(hWnd、message、wParam、lParam);
}
}
打破
案例WM_油漆:
{
PAINTSTRUCT-ps;
HDC HDC=开始喷漆(hWnd和ps);
//TODO:在此处添加任何使用hdc的图形代码。。。
端漆(hWnd和ps);
}
打破
案例WM_销毁:
PostQuitMessage(0);
打破
违约:
返回DefWindowProc(hWnd、message、wParam、lParam);
}
返回0;
}
//关于框的消息处理程序。
INT_PTR回调应用程序::About(HWND hDlg、UINT消息、WPARAM WPARAM、LPARAM LPARAM)
{
未引用的_参数(lpram);
开关(信息)
{
案例WM_初始化对话框:
返回(INT_PTR)TRUE;
case WM_命令:
if(LOWORD(wParam)==IDOK | | LOWORD(wParam)==IDCANCEL)
{
EndDialog(hDlg、LOWORD(wParam));
返回(INT_PTR)TRUE;
} 
打破
} 
返回(INT_PTR)FALSE;

我希望错误在这些代码段中。如果不是,我很乐意提供更多的代码。我已经做了研究,我真的不知道问题出在哪里。我知道about函数的回调必须是静态的,我相信它是静态的。除此之外,我不知道是什么导致它抛出异常。感谢您的帮助elp您可以给我。

无法使用您提供的代码重现此问题。以下是基于您的代码片段的示例,对我有效。您可以参考

附录h

App.cpp

#include "App.h"

App::App(HINSTANCE hInstance, CONST WCHAR* clsName)
{
    App::MyRegisterClass(hInstance, clsName);
}

ATOM App::MyRegisterClass(HINSTANCE hInstance, CONST WCHAR* clsName)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = App::WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DIALOGBOXEXCEPTION));
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_DIALOGBOXEXCEPTION);
    wcex.lpszClassName = clsName;
    wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}

LRESULT CALLBACK App::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    App* pApp;
    if (message == WM_CREATE)
    {
        LPCREATESTRUCT pcs = (LPCREATESTRUCT)lParam;
        pApp = (App*)pcs->lpCreateParams;
        ::SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)pApp);
        return TRUE;
    }
    else
    {
        pApp = reinterpret_cast<App*>(static_cast<LONG_PTR>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA)));
        if (!pApp)
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
    switch (message)
    {
    case WM_COMMAND:
    {
        int wmId = LOWORD(wParam);
        // Parse the menu selections:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(NULL, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, pApp->About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }
    break;
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);
        // TODO: Add any drawing code that uses hdc here...
        EndPaint(hWnd, &ps);
    }
    break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Message handler for about box.
INT_PTR CALLBACK App::About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

在这里放置一个断点
DialogBox(pApp->getInstance()
pApp
很可能是一个空的或无效的点。如果
About
是静态的,您甚至可以在调用
DialogBox
函数时使用
App::About
而不是
pApp->About
。甚至
pApp->getInstance()
可以替换为默认为当前应用程序的
NULL
。“我希望错误在这些代码片段中”。在调试器下运行程序。当抛出异常时,检查调用堆栈,如果需要,切换到您的最后一个函数。检查所有指针。
PtrToUlong
可以在64位模式下损坏指针。将整个项目放在某个地方,这样更容易检查。@DanielSęk的方法也适用于这里,
PtrToUlong(pApp)
将截断指针并在64位编译中中断代码。安全转换将改为
ULONG\u PTR
。@dxiv Right。已更新。谢谢。