在设置/删除窗口子类时正确传递/删除数据

时间:2014-02-22 07:25:56

标签: c++ winapi memory-leaks subclassing

引言及相关资料:

我在edit control中有多个dialog box需要接受浮点数并且locale知道。我决定用{实现此行为{1}} subclassing s。

为了实现edit control认知,我决定将结构传递给SetWindowSubclass(它将保存有关小数点分隔符,负号等的数据......)作为locale参数。

字段的值在dwRefData 中设置但如果用户更改WM_CREATE中的设置,则可能会更改,因此我决定更新字段的值以响应Control Panel->Regional and Language Settings消息。

为了避免将此结构设为全局,我决定将其设为WM_SETTINGCHANGE并在主窗口的过程中声明它。我将把它作为static API的LPARAM参数传递给对话框。

问题:

我不知道如何将上述结构正确传递给CreateDialogParamCreateDialogParam

问题还在于正确删除SetWindowSubclass ,以避免内存泄漏。

我努力解决这个问题:

在通过互联网搜索后,我找不到任何有用的东西,所以现在我只有一个概念性的解决方案。

看起来应该是这样的:

subclass

在我的//declare our structure that holds locale info struct locale_structure { wchar_t NegativeSign; wchar_t separator; }; //in my main window procedure: static locale_structure MyStruct; case WM_CREATE: { //get locale info about separator, negative sign and so on... MyStruct->separator = //... MyStruct->NegativeSign = //... } return 0L; case WM_SETTINGCHANGE: { //update locale info about separator, negative sign and so on... MyStruct->NegativeSign = //... MyStruct->separator = //... //... } // in the WM_COMMAND, to the response to a button click, pass MyStruct: hwndSomeDlg = CreateDialogParam( ..., (LPARAM)MyStruct ); 我应该dialog box /删除subclass,如下所示:

subclass

问题:

  1. 我应该如何将case WM_INITDIALOG: { /******** This is the tricky part ***********/ /// get locale structure from lParam locale_structure MyStruct = ( locale_structure )lParam; // pass it properly to subclassing procedures SetWindowSubclass( GetDlgItem( hDlg, IDC_EDIT1 ), ..., MyStruct ); SetWindowSubclass( GetDlgItem( hDlg, IDC_EDIT2 ), ..., MyStruct ); /************** other stuff ***********************/ } return TRUE; case WM_CLOSE: { // perform proper cleanup to avoid memory leaks RemoveWindowSubclass( ... ); } 传递给MyStructCreateDialogParam

  2. 如何删除SetWindowSubclass 以避免内存泄漏

  3. 我假设在subclassing中也会发生一些内存分配和解除分配,你能指导我如何正确地做到这一点吗?

  4. 2014年2月22日编辑

    我提交的代码实现了我的努力解决这个问题部分中描述的概念。

    程序使主窗口显示一个启动对话框的按钮。该对话框包含两个子类编辑控件。一切正常,所以我现在唯一关心的是我是否正确删除了结构。

    只需创建一个空项目并复制/粘贴所需的文件:

    subclassing procedure

    resource.h

    //{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by resource.rc // #define IDD_DIALOG1 101 #define IDC_EDIT1 1001 #define IDC_EDIT2 1002 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1003 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif

    resource.rc

    // Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) #endif //_WIN32 #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Dialog // IDD_DIALOG1 DIALOGEX 0, 0, 316, 180 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Dialog" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "OK",IDOK,205,159,50,14 PUSHBUTTON "Cancel",IDCANCEL,259,159,50,14 EDITTEXT IDC_EDIT1,23,20,94,17,ES_AUTOHSCROLL EDITTEXT IDC_EDIT2,23,65,90,21,ES_AUTOHSCROLL END ///////////////////////////////////////////////////////////////////////////// // // DESIGNINFO // #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO BEGIN IDD_DIALOG1, DIALOG BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 309 TOPMARGIN, 7 BOTTOMMARGIN, 173 END END #endif // APSTUDIO_INVOKED #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED

    main.cpp

    编辑结束

    感谢您的时间和帮助。

    最好的问候。

1 个答案:

答案 0 :(得分:1)

编辑2:

这是一个有效的例子(我希望):

#include "resource.h"
#include <windows.h>
#include <commctrl.h>
#include <stdlib.h>
#include <locale.h>
#include <stdio.h>

#pragma comment( lib, "comctl32.lib")

const wchar_t g_szClassName[] = L"myWindowClass";

// structure to hold locale info 
typedef struct LocaleInfo
{
    size_t NegativeSize, DecimalSize;
    wchar_t *NegativeSign, *DecimalSeparator;
    LocaleInfo()
    {
        NegativeSize = 0;
        DecimalSize = 0;
        NegativeSign = NULL;
        DecimalSeparator = NULL;
    }
    ~LocaleInfo()
    {
        if (NegativeSign != NULL)
        {
            delete[] NegativeSign;
            NegativeSign = NULL;
        }
        if (DecimalSeparator != NULL)
        {
            delete[] DecimalSeparator;
            DecimalSeparator = NULL;
        }
    }
}*pLocaleInfo;

void ReallocateInfo(wchar_t *&InsideArray, size_t &InsideSize, size_t NewSize)
{
    if (NewSize == 0)
        return;

    wchar_t *NewArray = new wchar_t[NewSize];
    delete[] InsideArray;
    InsideArray = NewArray;
    InsideSize = NewSize;
}

// subclassing procedure
LRESULT CALLBACK Decimalni(HWND hwnd, UINT message,
    WPARAM wParam, LPARAM lParam,
    UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    pLocaleInfo li = (pLocaleInfo)dwRefData;

    switch (message)
    {
    case WM_CHAR:
    {
        // accept digits,decimal separatorand negative sign
        // this validation is just an example

        if ((isdigit(wParam)) || (wParam < L' '))
            break;
        else
        {
            for (size_t i = 0; i < 5; i++)
                if ((wParam == li->DecimalSeparator[i])
                    || (wParam == li->NegativeSign[i]))
                {
                    return DefSubclassProc(hwnd, message, wParam, lParam);
                    break;
                }
                else
                {
                    MessageBeep(0);
                    return FALSE;
                    break;
                }
        }
    }
        break;
    case WM_NCDESTROY:
        // should I delete structure here ??
        RemoveWindowSubclass(hwnd, Decimalni, 0);
        break;
    }
    return DefSubclassProc(hwnd, message, wParam, lParam);
}

// dialog box procedure
INT_PTR CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    switch (Message)
    {
    case WM_INITDIALOG:
    {
        // subclass edit control
        pLocaleInfo li = (pLocaleInfo)lParam;
        SetWindowSubclass(GetDlgItem(hwnd, IDC_EDIT1),
            Decimalni, 0, (DWORD_PTR)li);
        SetWindowSubclass(GetDlgItem(hwnd, IDC_EDIT2),
            Decimalni, 0, (DWORD_PTR)li);
    }
        return TRUE;
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDOK:
        case IDCANCEL:
            EndDialog(hwnd, IDCANCEL);
            break;
        }
        break;
    default:
        return FALSE;
    }
    return TRUE;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static pLocaleInfo li; // store decimal separator and minus sign

    switch (msg)
    {
    case WM_CREATE:
    {
        /************* load current locale settings *************/

        // max. len: language, country, code page
        wchar_t lpszLocale[64 + 64 + 16 + 3] = L"";
        wchar_t lpszVal[128];

        LCID nLCID = ::GetUserDefaultLCID(); // current LCID for user
        if (::GetLocaleInfo(nLCID, LOCALE_SENGLANGUAGE, lpszVal, 128))
        {
            wcscat_s(lpszLocale, 147, lpszVal); // language
            if (::GetLocaleInfo(nLCID, LOCALE_SENGCOUNTRY, lpszVal, 128))
            {
                wcscat_s(lpszLocale, 147, L"_"); // append country/region
                wcscat_s(lpszLocale, 147, lpszVal);
                if (::GetLocaleInfo(nLCID, LOCALE_IDEFAULTANSICODEPAGE,
                    lpszVal, 128))
                {
                    // missing code page or page number 0 is no error 
                    // (e.g. with Unicode)
                    int nCPNum = _wtoi(lpszVal);
                    if (nCPNum >= 10)
                    {
                        wcscat_s(lpszLocale, 147, L"."); // append code page
                        wcscat_s(lpszLocale, 147, lpszVal);
                    }
                }
            }
        }
        // set locale and LCID
        _wsetlocale(LC_ALL, lpszLocale);
        ::SetThreadLocale(nLCID);

        /*** get information for decimal separator and negative sign ***/

        li = new LocaleInfo;

        ReallocateInfo(li->DecimalSeparator, li->DecimalSize, GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, NULL, NULL));
        ReallocateInfo(li->NegativeSign, li->NegativeSize, GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SNEGATIVESIGN, NULL, NULL));

        GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL,
            li->DecimalSeparator,
            li->DecimalSize);

        GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SNEGATIVESIGN,
            li->NegativeSign,
            li->NegativeSize);

        /*** create a button that launches a test dialog box *****/

        HWND hButton = CreateWindowEx(0, L"Button",
            L"Test subclassed edit controls in dialog box",
            WS_BORDER | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            50, 50, 350, 80, hwnd, (HMENU)8001,
            GetModuleHandle(NULL), NULL);
    }
        break;

    case WM_SETTINGCHANGE:
        if (!wParam && !wcscmp((wchar_t*)lParam, L"intl"))
        {
            // max. len: language, country, code page
            wchar_t lpszLocale[64 + 64 + 16 + 3] = L"";
            wchar_t lpszVal[128];

            LCID nLCID = ::GetUserDefaultLCID(); // current LCID for user
            if (::GetLocaleInfo(nLCID, LOCALE_SENGLANGUAGE, lpszVal, 128))
            {
                wcscat_s(lpszLocale, 147, lpszVal); // language
                if (::GetLocaleInfo(nLCID, LOCALE_SENGCOUNTRY, lpszVal, 128))
                {
                    wcscat_s(lpszLocale, 147, L"_"); // append country/region
                    wcscat_s(lpszLocale, 147, lpszVal);
                    if (::GetLocaleInfo(nLCID, LOCALE_IDEFAULTANSICODEPAGE,
                        lpszVal, 128))
                    {
                        // missing code page or page number 0 is no error 
                        // (e.g. with Unicode)

                        int nCPNum = _wtoi(lpszVal);
                        if (nCPNum >= 10)
                        {
                            wcscat_s(lpszLocale, 147, L"."); // append code page
                            wcscat_s(lpszLocale, 147, lpszVal);
                        }
                    }
                }
            }
            // set locale and LCID
            _wsetlocale(LC_ALL, lpszLocale);
            ::SetThreadLocale(nLCID);

            /** update information for decimal separator and negative sign ***/

            ReallocateInfo(li->DecimalSeparator, li->DecimalSize, GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, NULL, NULL));
            ReallocateInfo(li->NegativeSign, li->NegativeSize, GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SNEGATIVESIGN, NULL, NULL));

            GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL,
                li->DecimalSeparator,
                li->DecimalSize);

            GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SNEGATIVESIGN,
                li->NegativeSign,
                li->NegativeSize);

            return 0L;
        }
        else
            break;
    case WM_COMMAND:
    {
        if (LOWORD(wParam) == 8001)
        {
            DialogBoxParam(GetModuleHandle(NULL),
                MAKEINTRESOURCE(IDD_DIALOG1), hwnd, DlgProc, (LPARAM)li);
        }
    }
        return 0L;
    case WM_CLOSE:
    {
        delete li;
        DestroyWindow(hwnd);
    }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if (!RegisterClassEx(&wc))
    {
        MessageBox(NULL, L"Window Registration Failed!", L"Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    hwnd = CreateWindowEx(
        0,
        g_szClassName,
        L"theForger's Tutorial Application",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 480, 320,
        NULL, NULL, hInstance, NULL);

    if (hwnd == NULL)
    {
        MessageBox(NULL, L"Window Creation Failed!", L"Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

修改

一切都很好。您在WM_NCDESTROY上删除它是正确的,因为它总是被调用(有时可能会跳过WM_CLOSE)。你仍然忘记了{} WM_CLOSE,所以当编译器决定你需要问题时可能会遇到一些问题。

应该使用智能指针,因为如果出现问题,它应该为你释放内存,但是由你来决定。另外一个好处是它很容易适应你的代码,你基本上什么都不做。最后一点,这个“SmartPointer”是我的创作,可能仍然不完整,其他选择是unique_ptrshared_ptr以及更多可以在互联网上找到的。

你去了:

#include "resource.h"
#include <Windows.h>
#include <commctrl.h>
#include <stdlib.h>
#include <locale.h>
#include <stdio.h>
#include "SmartPointer.h"

#pragma comment( lib, "comctl32.lib")

const wchar_t g_szClassName[] = L"myWindowClass";

// structure to hold locale info 
struct LocaleInfo
{
    wchar_t NegativeSign[5];
    wchar_t DecimalSeparator[5];
};

// subclassing procedure
LRESULT CALLBACK Decimalni(HWND hwnd, UINT message,
    WPARAM wParam, LPARAM lParam,
    UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    SmartPointer<LocaleInfo> *li = (SmartPointer<LocaleInfo>*)dwRefData;

    switch (message)
    {
    case WM_CHAR:
    {
        // accept digits,decimal separatorand negative sign
        // this validation is just an example

        if ((isdigit(wParam)) || (wParam < L' '))
            break;
        else
        {
            for (size_t i = 0; i < 5; i++)
                if ((wParam == (*li)->DecimalSeparator[i])
                    || (wParam == (*li)->NegativeSign[i]))
                {
                    return DefSubclassProc(hwnd, message, wParam, lParam);
                    break;
                }
                else
                {
                    MessageBeep(0);
                    return FALSE;
                    break;
                }
        }
    }
        break;
    case WM_NCDESTROY:
        // should I delete structure here ??
        RemoveWindowSubclass(hwnd, Decimalni, 0);
        break;
    }
    return DefSubclassProc(hwnd, message, wParam, lParam);
}

// dialog box procedure
INT_PTR CALLBACK DlgProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
    switch (Message)
    {
    case WM_INITDIALOG:
    {
        // subclass edit control
        SmartPointer<LocaleInfo> *li = (SmartPointer<LocaleInfo>*)lParam;
        SetWindowSubclass(GetDlgItem(hwnd, IDC_EDIT1),
            Decimalni, 0, (DWORD_PTR)li);
        SetWindowSubclass(GetDlgItem(hwnd, IDC_EDIT2),
            Decimalni, 0, (DWORD_PTR)li);
    }
        return TRUE;
    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDOK:
        case IDCANCEL:
            EndDialog(hwnd, IDCANCEL);
            break;
        }
        break;
    default:
        return FALSE;
    }
    return TRUE;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static SmartPointer<LocaleInfo> li; // store decimal separator and minus sign

    switch (msg)
    {
    case WM_CREATE:
    {
        /************* load current locale settings *************/

        // max. len: language, country, code page
        wchar_t lpszLocale[64 + 64 + 16 + 3] = L"";
        wchar_t lpszVal[128];

        LCID nLCID = ::GetUserDefaultLCID(); // current LCID for user
        if (::GetLocaleInfo(nLCID, LOCALE_SENGLANGUAGE, lpszVal, 128))
        {
            wcscat_s(lpszLocale, 147, lpszVal); // language
            if (::GetLocaleInfo(nLCID, LOCALE_SENGCOUNTRY, lpszVal, 128))
            {
                wcscat_s(lpszLocale, 147, L"_"); // append country/region
                wcscat_s(lpszLocale, 147, lpszVal);
                if (::GetLocaleInfo(nLCID, LOCALE_IDEFAULTANSICODEPAGE,
                    lpszVal, 128))
                {
                    // missing code page or page number 0 is no error 
                    // (e.g. with Unicode)
                    int nCPNum = _wtoi(lpszVal);
                    if (nCPNum >= 10)
                    {
                        wcscat_s(lpszLocale, 147, L"."); // append code page
                        wcscat_s(lpszLocale, 147, lpszVal);
                    }
                }
            }
        }
        // set locale and LCID
        _wsetlocale(LC_ALL, lpszLocale);
        ::SetThreadLocale(nLCID);

        /*** get information for decimal separator and negative sign ***/

        li = SmartPointer<LocaleInfo>(LocaleInfo());

        GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL,
            li->DecimalSeparator,
            sizeof(li->DecimalSeparator) / sizeof(li->DecimalSeparator[0]));

        GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SNEGATIVESIGN,
            li->NegativeSign,
            sizeof(li->NegativeSign) / sizeof(li->NegativeSign[0]));

        /*** create a button that launches a test dialog box *****/

        HWND hButton = CreateWindowEx(0, L"Button",
            L"Test subclassed edit controls in dialog box",
            WS_BORDER | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            50, 50, 350, 80, hwnd, (HMENU)8001,
            GetModuleHandle(NULL), NULL);
    }
        break;

    case WM_SETTINGCHANGE:
        if (!wParam && !wcscmp((wchar_t*)lParam, L"intl"))
        {
            // max. len: language, country, code page
            wchar_t lpszLocale[64 + 64 + 16 + 3] = L"";
            wchar_t lpszVal[128];

            LCID nLCID = ::GetUserDefaultLCID(); // current LCID for user
            if (::GetLocaleInfo(nLCID, LOCALE_SENGLANGUAGE, lpszVal, 128))
            {
                wcscat_s(lpszLocale, 147, lpszVal); // language
                if (::GetLocaleInfo(nLCID, LOCALE_SENGCOUNTRY, lpszVal, 128))
                {
                    wcscat_s(lpszLocale, 147, L"_"); // append country/region
                    wcscat_s(lpszLocale, 147, lpszVal);
                    if (::GetLocaleInfo(nLCID, LOCALE_IDEFAULTANSICODEPAGE,
                        lpszVal, 128))
                    {
                        // missing code page or page number 0 is no error 
                        // (e.g. with Unicode)

                        int nCPNum = _wtoi(lpszVal);
                        if (nCPNum >= 10)
                        {
                            wcscat_s(lpszLocale, 147, L"."); // append code page
                            wcscat_s(lpszLocale, 147, lpszVal);
                        }
                    }
                }
            }
            // set locale and LCID
            _wsetlocale(LC_ALL, lpszLocale);
            ::SetThreadLocale(nLCID);

            /** update information for decimal separator and negative sign ***/

            GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL,
                li->DecimalSeparator,
                sizeof(li->DecimalSeparator) / sizeof(li->DecimalSeparator[0]));

            GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SNEGATIVESIGN,
                li->NegativeSign,
                sizeof(li->NegativeSign) / sizeof(li->NegativeSign[0]));

            return 0L;
        }
        else
            break;
    case WM_COMMAND:
    {
        if (LOWORD(wParam) == 8001)
        {
            DialogBoxParam(GetModuleHandle(NULL),
                MAKEINTRESOURCE(IDD_DIALOG1), hwnd, DlgProc, (LPARAM)li);
        }
    }
        return 0L;
    case WM_CLOSE:
    {
        DestroyWindow(hwnd);
        break;
    }
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if (!RegisterClassEx(&wc))
    {
        MessageBox(NULL, L"Window Registration Failed!", L"Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    hwnd = CreateWindowEx(
        0,
        g_szClassName,
        L"theForger's Tutorial Application",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 480, 320,
        NULL, NULL, hInstance, NULL);

    if (hwnd == NULL)
    {
        MessageBox(NULL, L"Window Creation Failed!", L"Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

  1. 如果我是你,我会想要通过SetWindowSubclass()CreateDialogParam()传递一个指针(最好是一个智能指针,它可以来自STD或自定义)。通过这种方式,它可以反映您在所有窗口中对结构进行的更改。一些简短的程序会很好,因为附近没有任何对话框模板,所以我不能给你一个如何将它传递给函数的例子。

  2. 我认为删除WM_CLOSE上的子类应该可以正常工作。

  3. 更多信息会很好。


  4. struct locale_structure
    {
        wchar_t NegativeSign;
        wchar_t separator;
    };
    
    static SmartPointer<locale_structure> MyStruct;
    

    #ifndef __SMART_POINTER
    #define __SMART_POINTER
    
    #include <wtypes.h>
    #include <utility>
    
    template <class Type>
    class SmartPointer
    {
    private:
        void SmartDelete()
        {
            if (Pointer != nullptr && RefCount != nullptr && Size != nullptr)
            {
                if (RefCount[0] > 0)
                    RefCount[0]--;
                else
                {
                    if (Size[0] == 0)
                        delete Pointer;
                    else
                        delete[] Pointer;
                    delete RefCount;
                    delete Size;
                }
                Pointer = nullptr;
                RefCount = nullptr;
                Size = nullptr;
            }
        }
        Type* Pointer;
        size_t* Size;
        UINT* RefCount;
    public:
        UINT size()
        {
            if (Pointer != NULL && RefCount != NULL && Size != NULL)
            {
                if (Size[0] == 0)
                    return 1;
                else
                    return Size[0];
            }
            else
                return 0;
        }
        SmartPointer() : Pointer(nullptr), Size(nullptr), RefCount(nullptr) {}
    
        Type& operator*() { return *Pointer; }
        const Type& operator*() const { return *Pointer; }
    
        Type* operator->() { return Pointer; }
        const Type* operator->() const { return Pointer; }
    
        Type& operator[](size_t index) { return Pointer[index]; }
        const Type& operator[](size_t index) const { return Pointer[index]; }
    
        template<typename ConversionType>
        operator ConversionType() { return reinterpret_cast<ConversionType>(this); }
    
        SmartPointer(Type& Object, size_t Size = 0)
        {
            RefCount = new UINT();
            this->Size = new size_t(Size);
            if (Size == 0)
                Pointer = new Type(std::move(Object));
            else
            {
                Pointer = new Type[Size];
                Pointer[0] = std::move(Object);
                for (size_t i = 1; i < Size; i++)
                    Pointer[i] = Pointer[0];
            }
        }
        ~SmartPointer() { SmartDelete(); }
        SmartPointer(SmartPointer &&OtherSP)
        {
            if (Pointer != OtherSP.Pointer)
            {
                SmartDelete();
                Size = OtherSP.Size;
                Pointer = OtherSP.Pointer;
                RefCount = OtherSP.RefCount;
                OtherSP.Size = nullptr;
                OtherSP.Pointer = nullptr;
                OtherSP.RefCount = nullptr;
            }
        }
        SmartPointer& operator=(SmartPointer &&OtherSP)
        {
            if (Pointer != OtherSP.Pointer)
            {
                SmartDelete();
                Size = OtherSP.Size;
                Pointer = OtherSP.Pointer;
                RefCount = OtherSP.RefCount;
                OtherSP.Size = nullptr;
                OtherSP.Pointer = nullptr;
                OtherSP.RefCount = nullptr;
            }
    
            return *this;
        }
        SmartPointer(const SmartPointer &OtherSP)
        {
            if (Pointer != OtherSP.Pointer)
            {
                SmartDelete();
                Size = OtherSP.Size;
                Pointer = OtherSP.Pointer;
                RefCount = OtherSP.RefCount;
                RefCount[0]++;
            }
            else
                RefCount[0]++;
        }
        SmartPointer& operator=(const SmartPointer &OtherSP)
        {
            if (Pointer != OtherSP.Pointer)
            {
                SmartDelete();
                Size = OtherSP.Size;
                Pointer = OtherSP.Pointer;
                RefCount = OtherSP.RefCount;
                RefCount[0]++;
            }
            else
                RefCount[0]++;
    
            return *this;
        }
    };
    
    #endif