在用户更改控制面板 - >区域和语言选项中的设置后,修改主窗口的区域设置 [英] Modify main window's locale after user changes settings in Control Panel->Regional and Language Options

查看:350
本文介绍了在用户更改控制面板 - >区域和语言选项中的设置后,修改主窗口的区域设置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简介及相关资讯: 我有 MS Access 2007 数据库,我使用 ADO



其他数据类型( string integer 。 ..)我也有一个 double



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



问题:



如果用户设置英语或塞尔维亚语组分隔符)区域设置和然后启动程序,但是当用户在程序运行时更改区域设置 时会出现此问题。



让我举一个小例子:



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



然后用户决定更改区域设置(在点击保存按钮之前,控制面板 - >区域和语言设置为 Windows XP



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



将文本转换为 double 必须出现 _wtof_l 现在将截断 1.25 1 ),因为我的程序使用默认 ANSIClocale ,没有适应它反映用户修改。



我的努力来解决问题:



为了防止这种情况,我需要调整我的程序的上述可能性 - 我需要设置我的区域设置在执行查询前选择的一个用户。



为此,我使用 message from answer to my previous question 以检测用户何时更改控制面板中的设置 - >区域和语言选项



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



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



这只会发生在我在程序工作期间更改区域设置时。如果我离开区域设置(99.9%的用户会),一切似乎都很好。



为了进一步帮助社区,我做了一个演示应用程序,说明了这个问题。
它将显示在此帖子末尾的附录部分。



问题:



我如何响应 WM_SETTINGCHANGE 消息,将我的应用程序的区域设置设置为用户当前选择的区域设置,所以我的保存按钮处理程序可以执行从 string double _wtof_l 函数正确转换?



谢谢。



最好的问候。



附录:



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



1.创建默认Win32项目在 Visual Studio



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

  case WM_CREATE:
{
_wsetlocale(LC_ALL,L); //在创建窗口时设置当前语言环境

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,LEdit,L,
WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL,
50,50,150,25,hWnd,(HMENU)8002,hInst,0);

//十进制数

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

HWND hButton = CreateWindowEx(0,LButton,LSave,
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,Lintl))
{
_wsetlocale(LC_ALL,L); //将其设置为当前语言环境
return 0L; //say我们处理它
}
else
break; //传递给默认窗口过程

4.In WM_COMMAND 处理程序添加以下案例 s:

 案例8004 :
{
//初始化COM
HRESULT hr = CoInitialize(NULL);

//格式连接字符串
wchar_t * bstrConnect = LProvider = Microsoft.ACE.OLEDB.12.0; \
数据源= .\\test.accdb ;

try
{

ADODB :: _ ConnectionPtr pConn(ADODB.Connection);

hr = pConn-> Open(bstrConnect,Ladmin,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); //文本
GetDlgItemText(hWnd,8003,number,5); // double

ADODB:_ CommandPtr pCmd(ADODB.Command);

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

pConn-> Close(); //关闭连接

CoUninitialize(); // uninitialize COM
}
else
throw _com_error(hr); //发生错误
}
catch(_com_error& e)
{
MessageBox(hWnd,(LPWSTR)(e.Description()),LError ,MB_OK |
MB_ICONERROR);

CoUninitialize();
}

}
break;

5.创建 MS Access 2007 MyTable 并添加2个字段 field1 code>作为 TEXT 字段,并添加 field2 ,即 double

解决方案

问题是当前 locale



我使用了错误的函数。



我不想偷其他人的点数,因此这里是我得到解决方案的链接。



这样,任何时候用户更改控制面板中的本地设置,我的应用程序将能够正确转换 string double 和我的 INSERT 查询不会有错误!



希望这会帮助其他人解决同样的问题。


INTRODUCTION AND RELEVANT INFORMATION:

I have MS Access 2007 database which I fill using ADO.

Among other data types ( string, integer...) I also have a double.

Since I work on Windows XP and use pure Win32 API to create GUI, I collect data from edit controls with GetDlgItemText API and then I convert that text into double using _wtof_l.

PROBLEM:

Everything works well if the user sets English or Serbian ( we use European notation for decimal and group separator ) locale and then starts the program, but the problem occurs when user changes locale settings while the program is working.

Let me demonstrate this on a small example:

Let us assume that user has English locale set.

Then user starts my application.

Then user decides to change the locale ( Control Panel->Regional and Language Settings for Windows XP ) before he hits the "Save" button.

After the changes apply he then enters data and then hits "save".

The error in converting text to double must occur ( _wtof_l will now truncate 1.25 to 1 ), since my program uses default ANSI "C" locale and did not adapt it to reflect users modification.

MY EFFORTS TO SOLVE THE PROBLEM:

To prevent this I need to adapt my program to the possibility described above-I need to set my locale to the one user selected before executing query.

To do so I use message from answer to my previous question to detect when user changes settings in Control Panel->Regional and Language Options.

Then I use _wsetlocale(LC_ALL,"") to set my applications locale to the one selected by the user.

However, wrong conversion from text to decimal number described above still occurs.

This only happens when I change the locale during my program's work. If I leave locale untouched ( as 99.9% of users will ) everything seems to work fine.

To further help the community I have made a demo application that illustrates the problem. It will be presented in the APPENDIX section at the end of this post.

QUESTION:

How can I respond to WM_SETTINGCHANGE message to set my application's locale to the one currently selected by the user so my "save" button handler can perform proper conversion from string to double with _wtof_l function?

Thank you.

Best regards.

APPENDIX:

Steps to create the demo application that illustrates my problem:

1.Create default Win32 project in Visual Studio.

2.Add the following WM_CREATE handler:

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.Add the following handler to detect when user changes locale settings

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.In WM_COMMAND handler add the following 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.Create MS Access 2007 database in the project folder.

6.Create table MyTable and add 2 fields field1 as TEXT field, and add field2 which is double.

解决方案

The problem was in improper setting of the current locale.

I was using the wrong function to do that.

I do not wish to steal other people's credits so here is the link where I got the solution from.

This way, any time user changes local settings in Control Panel, my application will be able to properly convert string to double and my INSERT queries will not have errors!

Hopefully this will help others with the same problem.

这篇关于在用户更改控制面板 - >区域和语言选项中的设置后,修改主窗口的区域设置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆