用户更改控制面板中的设置后,修改主窗口的区域设置 - >区域和语言选项

时间:2014-02-03 00:20:58

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

引言及相关资料:

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

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

由于我使用Windows XP并使用纯Win32 API来创建GUI,因此我使用editGetDlgItemText API控件收集数据,然后将该文本转换为{{1使用double

问题:

如果用户设置英语或塞尔维亚语(我们使用欧洲符号表示十进制和组分隔符)语言环境,然后启动程序,一切运行良好,但是当用户更改语言环境设置时会出现问题该计划正在运作。

让我用一个小例子证明这一点:

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

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

然后,用户在点击“保存”按钮之前决定更改区域设置(_wtof_l的{​​{1}})。

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

将文本转换为Control Panel->Regional and Language Settings时出现错误(Windows XP现在会将double截断为_wtof_l),因为我的程序使用默认1.25并且不适应它以反映用户的修改。

我努力解决问题:

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

为此,我使用message from answer to my previous question检测用户何时更改1中的设置。

然后我使用ANSI "C" locale将我的应用程序区域设置设置为用户选择的区域设置。

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

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

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

问题:

如何回复Control Panel->Regional and Language Options消息,将我的应用程序的区域设置设置为用户当前选择的区域,以便我的“保存”按钮处理程序可以执行从_wsetlocale(LC_ALL,"")WM_SETTINGCHANGE的正确转换string功能?

谢谢。

最好的问候。

附录:

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

1.在double中创建_wtof_l

2.添加以下default Win32 project处理程序:

Visual Studio

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

WM_CREATE

4.在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; 处理程序中添加以下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 s:

WM_COMMAND

5.在项目文件夹中创建case数据库。

6.创建表格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; 并添加2个字段MS Access 2007作为MyTable字段,并添加field1 TEXT

1 个答案:

答案 0 :(得分:3)

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

我使用错误的功能来做到这一点。

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

这样,只要用户更改控制面板中的本地设置,我的应用就能正确地将string转换为doubleINSERT个查询不会有错误!

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