关于文本显示的问题,请高手们看看,不解决不结贴,解决另有百分相送

时间:2022-07-07 21:26:44
我想让其它程序在不同默认语言(已经安装相应的语言支持)的系统上正常显示,我做了API HOOK,在TextoutA drawtextexA 上做了API(HOOK部分是成功的),一切都没有问题,但发现一般程序仅有少量文本使用,一般程序会调用哪些函数、消息来显示文本?另外还有一些问题一起请教

问题1:
我将得到的multibyte转成widechar 并调用带w的函数,但结果和没有HOOK一样,也尝试用传入的dc selectobject一个我建立的HFONT再调用显示函数,但在和程序资源定义不同的系统就显示乱码,有部分button显示用函数转换了,但仍然显示乱码
问题2:
使用WM_SETTEXT CB_ADDSTRING CB_SETITEMDATA等消息会最终会调用什么API完成显示?
问题3:
静态资源文件中定义的在调用DialogBoxIndirectParam生成的时候DialogBoxIndirectParam会调用什么来显示其定义的文本?!

24 个解决方案

#1


问题 1:在 NT 系列的操作系统上,包括 2000 及 XP 等,TextOut 等函数的 A 版本在转换之后还是要调用 W 版本,因此你的工作与系统的默认实现是一致的,等于没有做。如果我理解没有错的话,你是计划让其他语言的 ANSI 版本程序(例如一个日语程序)在不同语言的平台上(例如中文 Windows 2000)显示正常,如果此结论成立,我将继续和你讨论,当前就此打住
问题 2、3:全部是使用文本绘制的 W 版本函数直接绘制(NT based Windows system)

#2


1.所以我才在ANSI函数上hook ,系统会调用当前代码页对 multibyte 转换再调用Wide函数,我指定了是936(简中)转换,但在目标(日文)系统仍然不能正常显示
2,3 具体会使用哪些函数来显示?!

事实上我的目的正好和你说的相反,现在公司的操作系统是日文的,我想用一些中文ANSI版的程序,但....

#3


自己顶一下

#4


日文系统里装个中文的IIS试试

#5


晕~~~~!!!

#6


关注.......

#7


你要先在目标线程里调用 SetThreadLocale 函数把该线程的语言环境设为简体中文,再调用转换函数 MultibyteToWideChar 就可以了。当然,调用时第一个参数不能用 CP_ACP, 而是应该用CP_THREAD_ACP。

#8


对不起,因为没有做实验,上面我说的可能有错。应该是把第一个参数设为正确的代码页值,你的需求应该是这样调用:MultiByteToWideChar(936, ...);

#9


不需要调用 SetThreadLocale;936 是简体中文的代码页值

#10


我之前做的就是在TextOutA上,跳到我的函数,我的函数将传入的值从multibyte到widechar ,再调用TextOutW,但如我前面所述,不行!仍然乱码,才来求教!

#11


我看了SetThreadLocale可能会有用,还没试,是不是说我只要在CreateThread上HOOK,在建完后就进我的函数用SetThreadLocale,就不用字符集转了!?

#12


你的 MultiByteToWideChar 的第一个参数是什么?

#13


SetThreadLocale() 应该没有多大用,看一下 MSDN 中说他的影响范围就知道了。

#14


SetThreadLocal只能对当前Thread设

MultiByteToWideChar(936,....)

#15


看上去还是不行,自己建的程序也不能正常显示,无论是widechar 还是setthreadlocal

#16


你再仔细看一下这个函数:LCMapString

#17


LCMapString看过了,好象也没用,简繁转换可以,日中好象没用

#18


我刚才在日文系统上试过了,用 936 的方法可以啊,要不要我把源代码贴出来?

#19


在中文系统上创建一个对话框应用程序,上面放 3 个按钮,功能分别为直接输出,使用 CP_ACP 转换为 UNICODE 后输出以及使用 936 转换为 UNICODE 后输出;相应代码如下;

char* g_szText = "我是光荣的挨踢人员。";
int g_cchText = lstrlen(g_szText);
wchar_t g_wszText[MAX_PATH];

void CXXXDlg::OnBtnDirect() 
{
MessageBox(g_szText);
}

void CXXXDlg::OnBtnUnicode() 
{
int cch = MultiByteToWideChar(CP_ACP, 0, g_szText, g_cchText, g_wszText, MAX_PATH);
g_wszText[cch] = 0;
::MessageBoxW(*this, g_wszText, NULL, MB_OK);
}

void CXXXDlg::OnBtnUnicode2() 
{
int cch = MultiByteToWideChar(936, 0, g_szText, g_cchText, g_wszText, MAX_PATH);
g_wszText[cch] = 0;
::MessageBoxW(*this, g_wszText, NULL, MB_OK);
}

运行结果:
1、在中文系统上 3 次输出完全一样
2、在日文系统上前 2 个输出均为乱码,第 3 次输出正常。

#20


BOOL WINAPI NewTextOut(HDC hdc, int nXStart,int nYStart, LPCTSTR lpString,int cbString)
{
int iLen;
BOOL rt;
LPWSTR lpwString;

iLen = MultiByteToWideChar (936, 0, lpString, -1, NULL,0);
lpwString = (LPWSTR) LocalAlloc(LMEM_FIXED,iLen*sizeof(WCHAR));
iLen = MultiByteToWideChar(936,0,lpString,-1,lpwString,iLen);
rt = TextOutW(hdc,nXStart,nYStart,lpwString,iLen);
MessageBoxW(NULL,lpwString,lpwString,MB_OK);
LocalFree(lpwString);
return rt;
}
我前几天就这么用的,无效!

#21


可我上面的代码成功了,兄弟,就差给你截图了!!

#22


我知道了,QQ的下拉已经成功转换,我没点过,加了LOG才知道,一看真高兴是中文了
但是BUTTON用TEXTOUT的好象不是中简码,所以转了还是错.....

#23


ニユヘィト」ハスー・ォト」ハス(フレムカTM)ヘノト」ハスマ鋧「ア」サ、ト」ハスイサハケモテエ惕侒OCKS5エ惕棈TTPエ惕桄ケモテ莟タタニ靹テ???清除??登?取消申?号?网??置登?登?网??置网??置登?登?取消取消申?号?申?号?清除??清除??
清面方方的是中简,后面的不知道是什么码,在日文中可以显示部分

#24


可以看懂的部分是记录TextOutA的结果,没有转之前就可以显示部分了,我用936 到widechar 不行,用 widechar 到932也不行,再转936也不行

#1


问题 1:在 NT 系列的操作系统上,包括 2000 及 XP 等,TextOut 等函数的 A 版本在转换之后还是要调用 W 版本,因此你的工作与系统的默认实现是一致的,等于没有做。如果我理解没有错的话,你是计划让其他语言的 ANSI 版本程序(例如一个日语程序)在不同语言的平台上(例如中文 Windows 2000)显示正常,如果此结论成立,我将继续和你讨论,当前就此打住
问题 2、3:全部是使用文本绘制的 W 版本函数直接绘制(NT based Windows system)

#2


1.所以我才在ANSI函数上hook ,系统会调用当前代码页对 multibyte 转换再调用Wide函数,我指定了是936(简中)转换,但在目标(日文)系统仍然不能正常显示
2,3 具体会使用哪些函数来显示?!

事实上我的目的正好和你说的相反,现在公司的操作系统是日文的,我想用一些中文ANSI版的程序,但....

#3


自己顶一下

#4


日文系统里装个中文的IIS试试

#5


晕~~~~!!!

#6


关注.......

#7


你要先在目标线程里调用 SetThreadLocale 函数把该线程的语言环境设为简体中文,再调用转换函数 MultibyteToWideChar 就可以了。当然,调用时第一个参数不能用 CP_ACP, 而是应该用CP_THREAD_ACP。

#8


对不起,因为没有做实验,上面我说的可能有错。应该是把第一个参数设为正确的代码页值,你的需求应该是这样调用:MultiByteToWideChar(936, ...);

#9


不需要调用 SetThreadLocale;936 是简体中文的代码页值

#10


我之前做的就是在TextOutA上,跳到我的函数,我的函数将传入的值从multibyte到widechar ,再调用TextOutW,但如我前面所述,不行!仍然乱码,才来求教!

#11


我看了SetThreadLocale可能会有用,还没试,是不是说我只要在CreateThread上HOOK,在建完后就进我的函数用SetThreadLocale,就不用字符集转了!?

#12


你的 MultiByteToWideChar 的第一个参数是什么?

#13


SetThreadLocale() 应该没有多大用,看一下 MSDN 中说他的影响范围就知道了。

#14


SetThreadLocal只能对当前Thread设

MultiByteToWideChar(936,....)

#15


看上去还是不行,自己建的程序也不能正常显示,无论是widechar 还是setthreadlocal

#16


你再仔细看一下这个函数:LCMapString

#17


LCMapString看过了,好象也没用,简繁转换可以,日中好象没用

#18


我刚才在日文系统上试过了,用 936 的方法可以啊,要不要我把源代码贴出来?

#19


在中文系统上创建一个对话框应用程序,上面放 3 个按钮,功能分别为直接输出,使用 CP_ACP 转换为 UNICODE 后输出以及使用 936 转换为 UNICODE 后输出;相应代码如下;

char* g_szText = "我是光荣的挨踢人员。";
int g_cchText = lstrlen(g_szText);
wchar_t g_wszText[MAX_PATH];

void CXXXDlg::OnBtnDirect() 
{
MessageBox(g_szText);
}

void CXXXDlg::OnBtnUnicode() 
{
int cch = MultiByteToWideChar(CP_ACP, 0, g_szText, g_cchText, g_wszText, MAX_PATH);
g_wszText[cch] = 0;
::MessageBoxW(*this, g_wszText, NULL, MB_OK);
}

void CXXXDlg::OnBtnUnicode2() 
{
int cch = MultiByteToWideChar(936, 0, g_szText, g_cchText, g_wszText, MAX_PATH);
g_wszText[cch] = 0;
::MessageBoxW(*this, g_wszText, NULL, MB_OK);
}

运行结果:
1、在中文系统上 3 次输出完全一样
2、在日文系统上前 2 个输出均为乱码,第 3 次输出正常。

#20


BOOL WINAPI NewTextOut(HDC hdc, int nXStart,int nYStart, LPCTSTR lpString,int cbString)
{
int iLen;
BOOL rt;
LPWSTR lpwString;

iLen = MultiByteToWideChar (936, 0, lpString, -1, NULL,0);
lpwString = (LPWSTR) LocalAlloc(LMEM_FIXED,iLen*sizeof(WCHAR));
iLen = MultiByteToWideChar(936,0,lpString,-1,lpwString,iLen);
rt = TextOutW(hdc,nXStart,nYStart,lpwString,iLen);
MessageBoxW(NULL,lpwString,lpwString,MB_OK);
LocalFree(lpwString);
return rt;
}
我前几天就这么用的,无效!

#21


可我上面的代码成功了,兄弟,就差给你截图了!!

#22


我知道了,QQ的下拉已经成功转换,我没点过,加了LOG才知道,一看真高兴是中文了
但是BUTTON用TEXTOUT的好象不是中简码,所以转了还是错.....

#23


ニユヘィト」ハスー・ォト」ハス(フレムカTM)ヘノト」ハスマ鋧「ア」サ、ト」ハスイサハケモテエ惕侒OCKS5エ惕棈TTPエ惕桄ケモテ莟タタニ靹テ???清除??登?取消申?号?网??置登?登?网??置网??置登?登?取消取消申?号?申?号?清除??清除??
清面方方的是中简,后面的不知道是什么码,在日文中可以显示部分

#24


可以看懂的部分是记录TextOutA的结果,没有转之前就可以显示部分了,我用936 到widechar 不行,用 widechar 到932也不行,再转936也不行