我有MS Access 2007
数据库,我使用ADO
填充。
在其他数据类型(string
,integer
...)中,我还有一个double
。
由于我使用Windows XP
并使用纯Win32 API
来创建GUI,因此我使用edit
从GetDlgItemText 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
。
答案 0 :(得分:3)
问题在于当前locale
的设置不当。
我使用错误的功能来做到这一点。
我不想窃取其他人的信用,所以here是我从中得到解决方案的链接。
这样,只要用户更改控制面板中的本地设置,我的应用就能正确地将string
转换为double
和INSERT
个查询不会有错误!
希望这可以帮助其他人解决同样的问题。