📄 utf8edit.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: UTF8Edit.c,v 1.14 2002/11/21 22:01:58 pbj Exp $
This code subclasses an Edit control window so as to facilitate
the use of UTF8 with the window. This subclassing causes all
text sent to the window to be interpretted as UTF-8. The text sent
to the window is converted to UCS-2 and displayed as unicode text on
systems that support Unicode.
On NT/2K/XP we just subclass the edit control directly. On 9x we
actually create a new "RichEdit20W" window directly over the edit
control subclass that new windows. The original edit box is disabled
and hidden.
This approach better allows edit control to look/work as "normal"
edit controls.
____________________________________________________________________________*/
#include "windows.h"
#include "richedit.h"
#include "shlwapi.h"
#include "pgpUnicode.h"
#include "pgpUnicodeWin32.h"
#include "UTF8Edit.h"
// macro defitions
#define PACKVERSION(major,minor) MAKELONG(minor,major)
typedef struct
{
HWND hwndEdit;
HWND hwndRichEdit;
BOOL bUnicodeOS;
WNDPROC wpOrigProc;
HFONT hFont;
UINT uControlID;
} UTF8EditStruct;
// ______________________________________
//
// edit box subclass procedure
static LRESULT APIENTRY
sSubclassProc (
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
UTF8EditStruct* pues;
pues = (UTF8EditStruct*)GetWindowLong (hWnd, GWL_USERDATA);
if (uMsg == WM_HELP)
{
if (pues->hwndRichEdit)
{
// substitute in identifying info of edit control so as to allow
// context-sensitive help to work for RichEdit control
LPHELPINFO lphi = (LPHELPINFO)lParam;
lphi->dwContextId = pues->uControlID;
lphi->hItemHandle = pues->hwndEdit;
}
}
if (pues->bUnicodeOS)
{
return CallWindowProcW (pues->wpOrigProc,
hWnd, uMsg, wParam, lParam);
}
else
{
return CallWindowProcA (pues->wpOrigProc,
hWnd, uMsg, wParam, lParam);
}
}
// _______________________________________________
//
// get the version number of ComCtl32.dll
static DWORD
sGetComCtl32Version (VOID)
{
HINSTANCE hinstDll;
DWORD dwVersion = 0;
hinstDll = LoadLibrary (TEXT("comctl32.dll"));
if (hinstDll)
{
DLLGETVERSIONPROC pDllGetVersion;
pDllGetVersion =
(DLLGETVERSIONPROC)GetProcAddress (hinstDll, "DllGetVersion");
if (pDllGetVersion)
{
DLLVERSIONINFO dvi;
HRESULT hr;
ZeroMemory (&dvi, sizeof(dvi));
dvi.cbSize = sizeof(dvi);
hr = (*pDllGetVersion)(&dvi);
if (SUCCEEDED(hr))
dwVersion = PACKVERSION(dvi.dwMajorVersion, dvi.dwMinorVersion);
}
FreeLibrary(hinstDll);
}
return dwVersion;
}
// ______________________________________
//
// initialize the subclassing
HWND
UTF8EditInit (
HWND hwndEdit)
{
OSVERSIONINFO osvi={0};
UTF8EditStruct* pues=NULL;
LOGFONT lf;
RECT rc;
DWORD dwStyle;
pues = malloc (sizeof(UTF8EditStruct));
memset (pues, 0, sizeof(UTF8EditStruct));
pues->hwndEdit = hwndEdit;
pues->uControlID = GetDlgCtrlID (hwndEdit);
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx (&osvi);
pues->bUnicodeOS = (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT);
SetWindowLong (hwndEdit, GWL_USERDATA, (LONG)pues);
SetProp (hwndEdit, "UTF8Edit", (HANDLE)1);
// if older than WinXP's version of Common Controls,
// then use the RichEdit control
if (sGetComCtl32Version() < PACKVERSION(6,0))
{
// deal with edit window itself
dwStyle = GetWindowLong (hwndEdit, GWL_STYLE);
GetWindowRect (hwndEdit, &rc);
ShowWindow (hwndEdit, SW_HIDE);
EnableWindow (hwndEdit, FALSE);
// create the RichEdit window
MapWindowPoints (NULL, GetParent (hwndEdit), (LPPOINT)&rc, 2);
dwStyle |= WS_BORDER;
rc.top -= 1;
rc.left -= 1;
pues->hwndRichEdit = CreateWindowEx (0, "RichEdit20W", NULL,
dwStyle, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
GetParent (hwndEdit), NULL, NULL, 0);
SetWindowPos (pues->hwndRichEdit, hwndEdit, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE);
if (dwStyle & ES_READONLY)
{
SendMessage (pues->hwndRichEdit, EM_SETBKGNDCOLOR,
0, GetSysColor (COLOR_BTNFACE));
}
//>>> the following line is RichEdit 3.0 specific
SendMessage (pues->hwndRichEdit,
EM_SETEDITSTYLE, SES_USEAIMM, SES_USEAIMM);
//>>> the following line is RichEdit 3.0 specific
SendMessage (pues->hwndRichEdit, EM_SETEDITSTYLE,
SES_EMULATESYSEDIT, SES_EMULATESYSEDIT);
SystemParametersInfo (
SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0);
pues->hFont = CreateFontIndirect (&lf);
SendMessage (pues->hwndRichEdit, WM_SETFONT, (WPARAM)pues->hFont, 0);
SetWindowLong (pues->hwndRichEdit, GWL_USERDATA, (LONG)pues);
SetProp (pues->hwndRichEdit, "UTF8Edit", (HANDLE)1);
}
else
{
// if using the standard edit control on WinXP, set the font
// to DEFAULT_GUI_FONT, it seems to have better Unicode support
GetObject (GetStockObject (DEFAULT_GUI_FONT),
sizeof(LOGFONT), &lf);
pues->hFont = CreateFontIndirect (&lf);
SendMessage (hwndEdit, WM_SETFONT, (WPARAM)pues->hFont, 0);
}
// if this is a unicode OS (NT onwards), subclass with SetWindowLongW
if (pues->bUnicodeOS)
{
if (pues->hwndRichEdit)
{
pues->wpOrigProc = (WNDPROC) SetWindowLongW (pues->hwndRichEdit,
GWL_WNDPROC, (LONG)sSubclassProc);
}
else
{
pues->wpOrigProc = (WNDPROC) SetWindowLongW (hwndEdit,
GWL_WNDPROC, (LONG)sSubclassProc);
}
}
// otherwise use SetWindowLong
else
{
// if not Unicode we know we're using the RichEdit control
pues->wpOrigProc = (WNDPROC) SetWindowLong (pues->hwndRichEdit,
GWL_WNDPROC, (LONG)sSubclassProc);
}
if (pues->hwndRichEdit)
return pues->hwndRichEdit;
else
return hwndEdit;
}
VOID
UTF8EditDestroy (HWND hwndEdit)
{
UTF8EditStruct* pues;
pues = (UTF8EditStruct*)GetWindowLong (hwndEdit, GWL_USERDATA);
if (pues)
{
if (pues->bUnicodeOS)
{
if (pues->hwndRichEdit)
{
SetWindowLongW (pues->hwndRichEdit,
GWL_WNDPROC, (LONG)pues->wpOrigProc);
}
else
{
SetWindowLongW (hwndEdit,
GWL_WNDPROC, (LONG)pues->wpOrigProc);
}
}
else
{
// if not Unicode we know we're using the RichEdit control
SetWindowLong (pues->hwndRichEdit,
GWL_WNDPROC, (LONG)pues->wpOrigProc);
}
if (pues->hFont)
DeleteObject (pues->hFont);
if (pues->hwndRichEdit)
{
RemoveProp (pues->hwndRichEdit, "UTF8Edit");
DestroyWindow (pues->hwndRichEdit);
}
SetWindowLong (hwndEdit, GWL_USERDATA, (LONG)0);
RemoveProp (hwndEdit, "UTF8Edit");
free (pues);
}
}
// ______________________________________
//
// get/set text
INT
UTF8EditGetTextLength (HWND hwnd)
{
UINT uout = 0;
UINT ulen;
WCHAR* wsz;
UTF8EditStruct* pues;
HWND hwndEdit;
pues = (UTF8EditStruct*)GetWindowLong (hwnd, GWL_USERDATA);
if (pues->bUnicodeOS)
{
if (pues->hwndRichEdit)
hwndEdit = pues->hwndRichEdit;
else
hwndEdit = hwnd;
ulen = CallWindowProcW (pues->wpOrigProc,
hwndEdit, WM_GETTEXTLENGTH, 0, 0) +1;
wsz = malloc (ulen * sizeof(WCHAR));
if (wsz)
{
ulen = CallWindowProcW (pues->wpOrigProc,
hwndEdit, WM_GETTEXT, (WPARAM)ulen, (LPARAM)wsz);
if (ulen)
pgpUCS2StringToUTF8 (wsz, ulen, NULL, 0, &uout);
free (wsz);
}
}
else
{
GETTEXTLENGTHEX gtle;
gtle.codepage = 1200; // Unicode
gtle.flags = GTL_NUMCHARS | GTL_CLOSE;
ulen = CallWindowProcA (pues->wpOrigProc,
pues->hwndRichEdit, EM_GETTEXTLENGTHEX, (WPARAM)>le, 0) +1;
wsz = malloc (ulen * sizeof(WCHAR));
if (wsz)
{
GETTEXTEX gte;
memset (>e, 0, sizeof(GETTEXTEX));
gte.cb = ulen * sizeof(WCHAR);
gte.codepage = 1200; // Unicode
ulen = CallWindowProcA (pues->wpOrigProc,
pues->hwndRichEdit, EM_GETTEXTEX, (WPARAM)>e, (LPARAM)wsz);
if (ulen)
{
pgpUCS2StringToUTF8 (wsz, ulen,
NULL, 0, &uout);
}
free (wsz);
}
}
return uout;
}
INT
UTF8EditGetText (
HWND hwnd,
LPSTR pszOut,
UINT ubuflen)
{
UINT uout = 0;
UINT ulen;
WCHAR* wsz;
UTF8EditStruct* pues;
HWND hwndEdit;
pues = (UTF8EditStruct*)GetWindowLong (hwnd, GWL_USERDATA);
if (pues->bUnicodeOS)
{
if (pues->hwndRichEdit)
hwndEdit = pues->hwndRichEdit;
else
hwndEdit = hwnd;
ulen = CallWindowProcW (pues->wpOrigProc,
hwndEdit, WM_GETTEXTLENGTH, 0, 0) +1;
wsz = malloc (ulen * sizeof(WCHAR));
if (wsz)
{
ulen = CallWindowProcW (pues->wpOrigProc,
hwndEdit, WM_GETTEXT, (WPARAM)ulen, (LPARAM)wsz);
if (ulen==0)
{
if(ubuflen>=1)
{
pszOut[0]=0;
}
}
else
{
pgpUCS2StringToUTF8 (wsz, ulen,
pszOut, ubuflen, &uout);
}
free (wsz);
}
}
else
{
ulen = CallWindowProcA (pues->wpOrigProc,
pues->hwndRichEdit, WM_GETTEXTLENGTH, 0, 0) +1;
wsz = malloc (ulen * sizeof(WCHAR));
if (wsz)
{
GETTEXTEX gte;
memset (>e, 0, sizeof(GETTEXTEX));
gte.cb = ulen * sizeof(WCHAR);
gte.codepage = 1200; // Unicode
ulen = CallWindowProcA (pues->wpOrigProc,
pues->hwndRichEdit, EM_GETTEXTEX, (WPARAM)>e, (LPARAM)wsz);
if (ulen==0)
{
if(ubuflen>=1)
{
pszOut[0]=0;
}
}
else
{
pgpUCS2StringToUTF8 (wsz, ulen,
pszOut, ubuflen, &uout);
}
free (wsz);
}
}
return uout;
}
INT
UTF8EditSetText (
HWND hwnd,
LPSTR psz)
{
WCHAR* wsz;
UINT ulen, uret;
UTF8EditStruct* pues;
HWND hwndEdit;
pues = (UTF8EditStruct*)GetWindowLong (hwnd, GWL_USERDATA);
pgpUTF8StringToUCS2 (psz, kPGPUnicodeNullTerminated, NULL, 0, &ulen);
wsz = (WCHAR*)malloc ((ulen+1) * sizeof(WCHAR));
if (wsz)
{
pgpUTF8StringToUCS2 (psz, kPGPUnicodeNullTerminated, wsz, ulen+1, NULL);
if (pues->hwndRichEdit)
hwndEdit = pues->hwndRichEdit;
else
hwndEdit = hwnd;
if (pues->bUnicodeOS)
{
uret = CallWindowProcW (pues->wpOrigProc,
hwndEdit, WM_SETTEXT, 0, (LPARAM)wsz);
}
else
{
uret = CallWindowProcA (pues->wpOrigProc,
hwndEdit, WM_SETTEXT, 0, (LPARAM)wsz);
}
free (wsz);
}
return uret;
}
HWND
UTF8EditGetHandle (
HWND hwnd)
{
UTF8EditStruct* pues;
if (GetProp (hwnd, "UTF8Edit") != NULL)
{
pues = (UTF8EditStruct*)GetWindowLong (hwnd, GWL_USERDATA);
if (pues)
{
if (pues->hwndRichEdit)
return pues->hwndRichEdit;
}
}
return hwnd;
}
HWND
UTF8EditGetEditHandle (
HWND hwnd)
{
UTF8EditStruct* pues;
if (GetProp (hwnd, "UTF8Edit") != NULL)
{
pues = (UTF8EditStruct*)GetWindowLong (hwnd, GWL_USERDATA);
if (pues)
{
return pues->hwndEdit;
}
}
return hwnd;
}
/*__Editor_settings____
Local Variables:
tab-width: 4
End:
vi: ts=4 sw=4
vim: si
_____________________*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -