我正在尝试通过 CodeBlocks 制作 Unicode 程序(波斯语),但似乎这并不容易!
这是我迄今为止尝试过的:
首先我通过Resedit程序创建Win32 GUI对话框项目和设计资源。 我在Resedit和CodeBlocks(设置->编辑器>编码设置)中将编码设置为UTF-8,并将字体设置为Tahoma(此字体包括波斯字符)。 在 Resedit Preview 和 CodeBlocks 编辑器中(当我打开资源文件时),所有内容都显示正确,但是当我编译项目时,字符显示不正确。
#include <windows.h>
#include <commctrl.h>
#include <richedit.h>
#include "resource.h"
//
// Dialog resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
DLG_MAIN DIALOG 0, 0, 186, 95
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SETFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
EXSTYLE WS_EX_LAYOUTRTL
CAPTION "ثبت"
FONT 8, "Tahoma"
{
PUSHBUTTON "تایید", 0, 75, 40, 50, 14, 0, WS_EX_LEFT
LTEXT "متن:", 0, 26, 20, 14, 9, SS_LEFT, WS_EX_LEFT
EDITTEXT 0, 50, 20, 100, 14, ES_AUTOHSCROLL, WS_EX_LEFT
}
//
// Manifest resources
//
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
1 RT_MANIFEST ".\\manifest.xml"
资源文件代码
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "resource.h"
HINSTANCE hInst;
BOOL CALLBACK DlgMain(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
{
}
return TRUE;
case WM_CLOSE:
{
EndDialog(hwndDlg, 0);
}
return TRUE;
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
}
}
return TRUE;
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
hInst=hInstance;
InitCommonControls();
return DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DlgMain);
}
Main.CPP(在代码块中)
第二我在CodeBlocks中创建Win32Gui框架项目并再次尝试构建这个窗口,但这次我在谷歌搜索后更改了一些内容。
#if defined(UNICODE) && !defined(_UNICODE)
#define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif
#include <tchar.h>
#include <windows.h>
#include "commctrl.h"
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
wchar_t szClassName[ ] = L"CodeBlocksWindowsApp";
int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nCmdShow)
{
HWND hwnd;
MSG messages;
WNDCLASSEXW wincl;
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure;
wincl.style = CS_DBLCLKS;
wincl.cbSize = sizeof (WNDCLASSEX);
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL;
wincl.cbClsExtra = 0;
wincl.cbWndExtra = 0;
wincl.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
if (!RegisterClassExW (&wincl))
return 0;
hwnd = CreateWindowExW (
WS_EX_LAYOUTRTL,
szClassName,
L"ثبت",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
285,
183,
HWND_DESKTOP,
NULL,
hThisInstance,
NULL
);
ShowWindow (hwnd, nCmdShow);
while (GetMessage (&messages, NULL, 0, 0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return messages.wParam;
}
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
HFONT hfont = CreateFont(-11, 0, 0, 0, 0, FALSE, FALSE, FALSE, 1, 0, 0, 0, 0, ("Tahoma"));
HWND btnhwnd = CreateWindowW(WC_BUTTONW, L"تایید", WS_VISIBLE | WS_CHILD | WS_TABSTOP, 111, 65, 75, 23, hwnd,NULL, NULL, 0);
SendMessageW(btnhwnd, WM_SETFONT, (WPARAM)hfont, TRUE);
HWND statichwnd = CreateWindowW( WC_STATICW, L"متن:", WS_VISIBLE | WS_CHILD | WS_GROUP | SS_LEFT, 38, 33, 21, 15, hwnd, NULL, NULL, 0);
SendMessageW(statichwnd, WM_SETFONT, (WPARAM)hfont, TRUE);
HWND edithwnd = CreateWindowW(WC_EDITW, L"", WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_BORDER | ES_AUTOHSCROLL, 74, 33, 150, 23, hwnd, NULL, NULL, 0);
SendMessageW(edithwnd, WM_SETFONT, (WPARAM)hfont, TRUE);
}
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
default:
return DefWindowProcW (hwnd, message, wParam, lParam);
}
return 0;
}
为了正确显示 unicode 字符,我更改了这些项目:
DefWindowProc to DefWindowProcW
SendMessage to SendMessageW
CreateWindow to CreateWindowExW
Char szClassName[ ] to wchar_t szClassName[ ]
WNDCLASS wincl to WNDCLASSEXW wincl
!RegisterClass (&wincl) to !RegisterClassExW (&wincl)
此函数/命令支持 unicode,但正如您所见,这些命令在 Win32 Dialog 项目中不存在!
搜索后我发现对话框项目中的这一行似乎导致 Unicode 无法正确显示:
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE
hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
和
return DialogBox(hInst, MAKEINTRESOURCE(DLG_MAIN), NULL
我尝试在 Visual Studio 中制作类似的项目,看看 Visual Studio 做了什么,我是否可以在代码块中做同样的事情。
Visual Studio win32对话框项目由资源文件和main.cpp文件组成,这些是代码:
#include <Windows.h>
#include <CommCtrl.h>
#include <tchar.h>
#include "resource.h"
#pragma comment(linker, \
"\"/manifestdependency:type='Win32' "\
"name='Microsoft.Windows.Common-Controls' "\
"version='6.0.0.0' "\
"processorArchitecture='*' "\
"publicKeyToken='6595b64144ccf1df' "\
"language='*'\"")
#pragma comment(lib, "ComCtl32.lib")
INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDCANCEL:
SendMessage(hDlg, WM_CLOSE, 0, 0);
return TRUE;
}
break;
case WM_CLOSE:
if(MessageBox(hDlg, TEXT("Close the program?"), TEXT("Close"),
MB_ICONQUESTION | MB_YESNO) == IDYES)
{
DestroyWindow(hDlg);
}
return TRUE;
case WM_DESTROY:
PostQuitMessage(0);
return TRUE;
}
return FALSE;
}
int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE h0, LPTSTR lpCmdLine, int nCmdShow)
{
HWND hDlg;
MSG msg;
BOOL ret;
InitCommonControls();
hDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_DIALOG1), 0, DialogProc, 0);
ShowWindow(hDlg, nCmdShow);
while((ret = GetMessage(&msg, 0, 0, 0)) != 0) {
if(ret == -1)
return -1;
if(!IsDialogMessage(hDlg, &msg)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
主要.cpp
// 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
/////////////////////////////////////////////////////////////////////////////
// Persian (fa-IR) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FAR)
LANGUAGE LANG_PERSIAN, SUBLANG_DEFAULT
#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, 223, 83
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_LAYOUTRTL
CAPTION "ثبت"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "تایید",IDOK,85,49,50,14
EDITTEXT IDC_EDIT1,61,28,98,14,ES_AUTOHSCROLL
LTEXT "نام:",IDC_STATIC,46,31,12,8
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_DIALOG1, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 216
TOPMARGIN, 7
BOTTOMMARGIN, 76
END
END
#endif // APSTUDIO_INVOKED
#endif // Persian (fa-IR) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
资源.rc
如您所见,Visual Studio 使用以下 winmain 函数定义:
int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE h0, LPTSTR lpCmdLine, int nCmdShow)
我尝试在代码块中使用 Visual Studio 源代码(复制粘贴源代码)来解决问题,但代码块无法执行它并导致以下错误:
undefined reference to '_WinMain@16
我什至尝试解决这个错误,但没有成功并且代码块崩溃了! 当我将 unicode 设置为 utf-16 时,代码块中也出现了惊人的错误(debug show #ifdef 命令有问题!)
Visual Studio 可以正确显示 Unicode 字符,但代码块却不能。 您对我的问题有何看法和建议? (感谢并抱歉我的长问题)
经过大量搜索和尝试/错误终于解决了问题。
我做了什么:
--将resource.rc文件保存为UTF-8编码
--将“#pragma code_page(65001)”添加到resource.rc文件的第一行(不带双引号)
--使用DialogBoxW代替DialogBox命令
--使用 MAKEINTRESOURCEW 而不是 MAKEINTRESOURCE
最后,所有 Unicode 文本都能正确显示。