【问题标题】:Modify main window's locale after user changes settings in Control Panel->Regional and Language Options用户更改控制面板->区域和语言选项中的设置后修改主窗口的区域设置
【发布时间】:2014-02-03 00:20:58
【问题描述】:

简介及相关资料:

我有MS Access 2007 数据库,我使用ADO 填写。

在其他数据类型(stringinteger...)中,我还有一个double

由于我使用Windows XP 并使用纯Win32 API 创建GUI,我使用GetDlgItemText APIedit 控件收集数据,然后使用_wtof_l 将该文本转换为double

问题:

如果用户设置英语或塞尔维亚语(我们使用欧洲符号作为小数和组分隔符)区域设置并然后启动程序,一切正常,但是当用户更改区域设置时会出现问题在程序运行时。

让我用一个小例子来演示一下:

让我们假设用户设置了英语语言环境。

然后用户启动我的应用程序。

然后用户决定在点击“保存”按钮之前更改区域设置(Control Panel->Regional and Language SettingsWindows XP)。

应用更改后,他输入数据,然后点击“保存”。

必须发生将文本转换为 double 的错误(_wtof_l 现在会将 1.25 截断为 1),因为我的程序使用默认的 ANSI "C" locale 并且没有对其进行调整以反映用户的修改。

我为解决问题所做的努力:

为了防止这种情况,我需要调整我的程序以适应上述可能性 - 我需要在执行查询之前将我的语言环境设置为选择的一个用户。

为此,我使用message from answer to my previous question 来检测用户何时更改Control Panel->Regional and Language Options 中的设置。

然后我使用_wsetlocale(LC_ALL,"") 将我的应用程序区域设置为用户选择的区域。

但是,仍然会出现上述从文本到十进制数的错误转换。

只有当我在程序运行期间更改语言环境时才会发生这种情况。如果我保持语言环境不变(99.9% 的用户会这样做),一切似乎都可以正常工作。

为了进一步帮助社区,我制作了一个演示应用程序来说明问题。 它将在本文末尾的附录部分中介绍。

问题:

如何回复WM_SETTINGCHANGE 消息以将我的应用程序的语言环境设置为用户当前选择的语言环境,以便我的“保存”按钮处理程序可以使用_wtof_l 函数执行从stringdouble 的正确转换?

谢谢。

最好的问候。

附录:

创建说明我的问题的演示应用程序的步骤:

1.在Visual Studio中创建default Win32 project

2.添加以下WM_CREATE处理程序:

case WM_CREATE:
    {
        _wsetlocale( LC_ALL, L"" ); //set current locale at window creation

        INITCOMMONCONTROLSEX iccex;
        memset( &iccex, 0, sizeof(INITCOMMONCONTROLSEX) );
        iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
        iccex.dwICC = ICC_STANDARD_CLASSES | ICC_TAB_CLASSES | ICC_BAR_CLASSES;
        InitCommonControlsEx( &iccex );

        // text

        HWND hEdit = CreateWindowEx( 0, L"Edit", L"", 
                         WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
                         50, 50, 150, 25, hWnd, (HMENU)8002, hInst, 0 );

        // decimal number

        HWND hEdit1 = CreateWindowEx( 0, L"Edit", L"", 
                         WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
                         250, 50, 150, 25, hWnd, (HMENU)8003, hInst, 0 );

        HWND hButton = CreateWindowEx( 0, L"Button", L"Save", 
                         WS_CHILD | WS_VISIBLE | WS_BORDER | BS_PUSHBUTTON,
                         50, 150, 150, 25, hWnd, (HMENU)8004, hInst, 0 );

        SendMessage( hEdit, EM_LIMITTEXT, (WPARAM)9, (LPARAM)0 );
        SendMessage( hEdit1, EM_LIMITTEXT, (WPARAM)4, (LPARAM)0 );

    }
    return 0L;

3.添加以下处理程序以检测用户何时更改区域设置

case WM_SETTINGCHANGE:
    if( !wParam && !wcscmp( (wchar_t*)lParam, L"intl" ) )
    {
        _wsetlocale( LC_ALL, L"" ); //set it to current locale
        return 0L; // "say" we handled it
    }
    else
        break; // pass it to default window procedure

4.在WM_COMMAND处理程序中添加以下cases:

case 8004:
    {
        // initialize COM
        HRESULT hr = CoInitialize(NULL);

        // format connection string
        wchar_t *bstrConnect= L"Provider=Microsoft.ACE.OLEDB.12.0; \
            Data Source = .\\test.accdb";

        try
        {

            ADODB::_ConnectionPtr pConn("ADODB.Connection");

            hr = pConn->Open(bstrConnect, L"admin", L"", ADODB::adConnectUnspecified);

            if ( SUCCEEDED(hr) )
            {
                wchar_t text[10], number[5];

                memset( &text, L'\0', sizeof(text) );
                memset( &number, L'\0', sizeof(number) );

                GetDlgItemText( hWnd, 8002, text, 10 );    // text
                GetDlgItemText( hWnd, 8003, number, 5 );   // double

                ADODB::_CommandPtr pCmd("ADODB.Command");

                pCmd->ActiveConnection = pConn;
                pCmd->CommandText = L" insert into MyTable ( field1, field2 ) values ( ?, ? );";
                pCmd->Parameters->Append( pCmd->CreateParameter( "?", ADODB::adDouble,
                                     ADODB::adParamInput, sizeof(double),
                                    _wtof_l( number, _get_current_locale() ) ) );
               pCmd->Parameters->Append( pCmd->CreateParameter( "?",
                                    ADODB::adVarWChar, ADODB::adParamInput, 
                                    wcslen(text), text ) );
               pCmd->Execute( NULL, NULL, ADODB::adCmdText );

               pConn->Close(); // close connection

               CoUninitialize(); // uninitialize COM
            }
            else
                throw _com_error(hr); //something failed-report it
        }
        catch(_com_error& e)
        {
            MessageBox(hWnd, (LPWSTR)(e.Description()), L"Error", MB_OK | 
                MB_ICONERROR );

            CoUninitialize();
        }

     }
     break;

5.在项目文件夹中创建MS Access 2007数据库。

6.创建表MyTable并添加2个字段field1作为TEXT字段,并添加field2double

【问题讨论】:

    标签: c++ winapi ms-access-2007 locale ado


    【解决方案1】:

    问题在于当前locale设置不当。

    我使用了错误的函数来做到这一点。

    我不想窃取其他人的积分,所以here 是我从中获得解决方案的链接。

    这样,只要用户在控制面板中更改本地设置,我的应用程序就能够正确地将string 转换为double,并且我的INSERT 查询不会出错!

    希望这能帮助其他有同样问题的人。

    【讨论】:

    • 我为你的诚实和谦逊投了你的票!
    • @user1793036:谢谢!
    猜你喜欢
    • 1970-01-01
    • 2011-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-12
    • 1970-01-01
    • 2018-12-28
    相关资源
    最近更新 更多