jiangsheng(蒋晟.Net) 兄请进来,帮我解决一下,一个感觉比较难得问题,贴了好几贴没人能解决的问题。

linuxyf 2006-01-06 03:51:03
这是我写的一个从IME词库里取得register word的程序,这段代码放在一个文件中是可以执行的。
代码如下:
#include "stdafx.h"
#include <Windows.h>
#include <string>
#include <exception>

using namespace std;

struct WordInfo
{
public:
string reading;
string description;
DWORD style;
};


static int cnt = 0;

UINT CALLBACK EnumRegisterWordProc(
LPCTSTR lpszReading,
DWORD dwStyle,
LPCTSTR lpszString,
LPVOID lpData
)
{
if (lpData)
{
((WordInfo*)lpData)[cnt].reading = lpszReading;
((WordInfo*)lpData)[cnt].description = lpszString;
((WordInfo*)lpData)[cnt].style = dwStyle;
}
return ++cnt;
}

//UINT (CALLBACK *pf)(LPCTSTR, DWORD, LPCTSTR, LPVOID);

void getRegisterWords()
{
try
{
HKL hKL = LoadKeyboardLayout("E0010411", KLF_SETFORPROCESS);
//pf = EnumRegisterWordProc;
//REGISTERWORDENUMPROC *p = EnumRegisterWordProc;
int num = ImmEnumRegisterWord(hKL, (REGISTERWORDENUMPROC)EnumRegisterWordProc, NULL, 0, NULL, NULL);
WordInfo *pRetVal = new WordInfo[num];
cnt = 0;
UINT ret1 = ImmEnumRegisterWord(hKL, (REGISTERWORDENUMPROC)EnumRegisterWordProc, NULL, 0, NULL, pRetVal);
delete []pRetVal;
} catch(...)
{

}
}


int main(int argc, CHAR* argv[])
{
getRegisterWords();
}

但当我把这段代码封装成一个类之后,编译就出错了。问题主要出在回调函数部分,但我解决不了了。
#include <Windows.h>
#include <string>
#include <exception>

using namespace std;

class ImmRegister {
private:
struct WordInfo
{
public:
string reading;
string description;
DWORD style;
};
static int cnt;

UINT CALLBACK EnumRegisterWordProc(
LPCTSTR lpszReading,
DWORD dwStyle,
LPCTSTR lpszString,
LPVOID lpData
)
{
if (lpData)
{
((WordInfo*)lpData)[cnt].reading = lpszReading;
((WordInfo*)lpData)[cnt].description = lpszString;
((WordInfo*)lpData)[cnt].style = dwStyle;
}
return ++cnt;
}
public:
static void createWordXML()
{
try
{
HKL hKL = LoadKeyboardLayout("E0010411", KLF_SETFORPROCESS);
int num = ImmEnumRegisterWord(hKL, (REGISTERWORDENUMPROC)EnumRegisterWordProc, NULL, 0, NULL, NULL);
WordInfo *pRetVal = new WordInfo[num];
cnt = 0;
UINT ret1 = ImmEnumRegisterWord(hKL, (REGISTERWORDENUMPROC)EnumRegisterWordProc, NULL, 0, NULL, pRetVal);
delete []pRetVal;
} catch(...)
{

}
}
};
...全文
508 35 打赏 收藏 转发到动态 举报
写回复
用AI写文章
35 条回复
切换为时间正序
请发表友善的回复…
发表回复
linuxyf 2006-01-17
  • 打赏
  • 举报
回复
wangk(倒之) 兄,再次表示感谢,你是正确的。揭帖了
TianChong 2006-01-14
  • 打赏
  • 举报
回复
讨论得很热烈啊,能取得词,就基本OK了,至于只保留了最后的一个词是出在逻辑判断的问题上了.
__________________ 2006-01-13
  • 打赏
  • 举报
回复
求求楼主了。给一分也行啊。xingxing好吧。
broccoli 2006-01-13
  • 打赏
  • 举报
回复
up
wangk 2006-01-12
  • 打赏
  • 举报
回复
你确定words.size()是1?把它打印出来,应该是词数才对呀。你在回调函数里面设断点看看调用是否正常。
linuxyf 2006-01-12
  • 打赏
  • 举报
回复
wangk(倒之) 兄,这回可以运行了,但有一个问题,就是不管有多少个词,最后返回的Vector,只保存了最后取的那个词,保存在第一个位置。其他的词都冲掉了。
wangk 2006-01-12
  • 打赏
  • 举报
回复
忘了改回调函数,这样在我机器上没问题。
UINT CALLBACK WordTool::EnumRegisterWordProc(LPCTSTR lpszReading, DWORD dwStyle, LPCTSTR lpszString, LPVOID lpData )
{
if (lpData)
{
WordInfo tmpData;
tmpData.reading = lpszReading;
tmpData.description = lpszString;
tmpData.style = dwStyle;
wordVector *pWords = (wordVector *)lpData;
pWords->push_back(tmpData);
}
return TRUE;
}
linuxyf 2006-01-12
  • 打赏
  • 举报
回复
wangk(倒之)兄,我也感觉你的方案不错,可我在运行这一句
的时候发生异常,异常信息如下:
UINT ret1 = ImmEnumRegisterWord(hKL, (REGISTERWORDENUMPROC)EnumRegisterWordProc, NULL, 0, NULL, &words);
Unhandled exception at 0x00416ca0 in IMETool.exe: 0xC0000005: Access violation reading location 0x00000000.

有可能发生什么错误了???
wangk 2006-01-11
  • 打赏
  • 举报
回复
几个问题:
1.*pRetVal = new WordInfo[num]; 什么时候释放?不释放会造成内存泄漏!
所以我建议改成这个样子:
typedef vector <WordInfo> wordVector;
static wordVector words;//它可以作为类的静态变量如果词库可以只有一个实例的话
words.resize(num);//更改数组大小为num
for(int i = 0; i < words.size(); i++)
{//这里获取数组的每个元素
words[i].reading=lpszReading;
}

=========== Word.h===============
#include <Windows.h>
#include <string>
#include <vector>
#include <exception>

using namespace std;
#pragma once

struct WordInfo
{
public:
string reading;
string description;
DWORD style;
};

typedef vector <WordInfo> wordVector;

class WordTool
{
private:
static wordVector words;
protected:
static UINT CALLBACK EnumRegisterWordProc(LPCTSTR lpszReading, DWORD dwStyle, LPCTSTR lpszString, LPVOID lpData );
public:
wordVector* getRegisterWords(int& wSize);
};
=========End Of Word.h==============

============Word.cpp==============
#include "stdafx.h"
#include "Word.h"
#pragma comment(lib,"imm32.lib")
#pragma comment(lib,"User32.lib")
wordVector WordTool::words;
UINT CALLBACK WordTool::EnumRegisterWordProc(LPCTSTR lpszReading, DWORD dwStyle, LPCTSTR lpszString, LPVOID lpData )
{
if (lpData)
{
WordInfo tmpData = {0};
tmpData.reading = lpszReading;
tmpData.description = lpszString;
tmpData.style = dwStyle;
wordVector *pWords = (wordVector *)lpData;
pWords->push_back(tmpData);
}
return TRUE;
}

wordVector* WordTool::getRegisterWords(int& wSize)
{
try
{
HKL hKL = LoadKeyboardLayout("E0010411", KLF_ACTIVATE);
words.clear();
UINT ret1 = ImmEnumRegisterWord(hKL, (REGISTERWORDENUMPROC)EnumRegisterWordProc, NULL, 0, NULL, &words);
return &words;
} catch(...)
{

}
return NULL;
}
==========End Of Word.cpp==============

wangk 2006-01-10
  • 打赏
  • 举报
回复
我不大清除你写了什么意思,特别是那个cnt.
反正就几个小错误:
1.using namespace std;要放在Word.h中因为你在里面用了string
2.最好加上在Word.h中#pragma once
3.class WordTool的定义的最后大括号缺少;。要看清楚啊!
4.定义static只要在声明中定义即可,不用实现中也定义。
5.我没发现你用到变量i,我把它改成了cnt。
=========== Word.h===============
#include <Windows.h>
#include <string>
#include <exception>

using namespace std;
#pragma once
struct WordInfo
{
public:
string reading;
string description;
DWORD style;
};

class WordTool
{
private:
static int cnt;

protected:
static UINT CALLBACK EnumRegisterWordProc(LPCTSTR lpszReading, DWORD dwStyle, LPCTSTR lpszString, LPVOID lpData );
public:
WordInfo* getRegisterWords(int& wSize);
};
=========End Of Word.h==============

============Word.cpp==============
#include "stdafx.h"
#include "Word.h"
#pragma comment(lib,"imm32.lib")
#pragma comment(lib,"User32.lib")
int WordTool::cnt = 0;
UINT CALLBACK WordTool::EnumRegisterWordProc(LPCTSTR lpszReading, DWORD dwStyle, LPCTSTR lpszString, LPVOID lpData )
{
if (lpData)
{
((WordInfo*)lpData)[cnt].reading = lpszReading;
((WordInfo*)lpData)[cnt].description = lpszString;
((WordInfo*)lpData)[cnt].style = dwStyle;
}
return ++cnt;
}

WordInfo* WordTool::getRegisterWords(int& wSize)
{
try
{
HKL hKL = LoadKeyboardLayout("E0010411", KLF_ACTIVATE);
int num = ImmEnumRegisterWord(hKL, (REGISTERWORDENUMPROC)EnumRegisterWordProc, NULL, 0, NULL, NULL);
wSize = num;
WordInfo *pRetVal = new WordInfo[num];
UINT ret1 = ImmEnumRegisterWord(hKL, (REGISTERWORDENUMPROC)EnumRegisterWordProc, NULL, 0, NULL, pRetVal);
return pRetVal;
} catch(...)
{

}
return NULL;
}

==========End Of Word.cpp==============
linuxyf 2006-01-10
  • 打赏
  • 举报
回复
wangk(倒之) 兄,非常感谢你的指点,关于cnt的应用,是这样的
int WordTool::cnt = 0;

主要是在回调函数中
UINT CALLBACK WordTool::EnumRegisterWordProc(LPCTSTR lpszReading, DWORD dwStyle, LPCTSTR lpszString, LPVOID lpData )
{
if (lpData)
{
((WordInfo*)lpData)[cnt].reading = lpszReading;
((WordInfo*)lpData)[cnt].description = lpszString;
((WordInfo*)lpData)[cnt].style = dwStyle;
}
return ++cnt;
}
用做数组的索引的

因为事先不知道词库中自定义的词究竟有多少个,所以int num = ImmEnumRegisterWord(hKL, (REGISTERWORDENUMPROC)EnumRegisterWordProc, NULL, 0, NULL, NULL); 这一句是用来得到词的个数,用来确定数组的大小的。因为词库中有几个词,回调函数就被调用了几次,所以作为索引的变量cnt没有定义在函数内部,而是定义到函数的外部了。如果定义在回调函数的内部,则每次调用都会指向数组的第一个元素。

下面WordInfo *pRetVal = new WordInfo[num]; 定义数组的大小。

UINT ret1 = ImmEnumRegisterWord(hKL, (REGISTERWORDENUMPROC)EnumRegisterWordProc, NULL, 0, NULL, pRetVal); 这一句是取出所有的词的。在这一句之前应该重置cnt的值为0。

关于cnt的使用,我感觉只能放在回调函数外,wangk(倒之) 兄有没有更好的方法???
wangk 2006-01-10
  • 打赏
  • 举报
回复
收到了,开始看ing。
linuxyf 2006-01-10
  • 打赏
  • 举报
回复
wangk(倒之)兄,你帮我看一下,我给你发邮件了
wangk 2006-01-09
  • 打赏
  • 举报
回复
你可以发到我得邮箱:
JujoKing在Hotmail.com
shmily1280 2006-01-09
  • 打赏
  • 举报
回复
MARK
回调函数只接触过一次,还是TAPI里的
zdleek 2006-01-09
  • 打赏
  • 举报
回复
已经有人说了,加个STATIC就可以
static UINT CALLBACK EnumRegisterWordProc(
LPCTSTR lpszReading,
DWORD dwStyle,
LPCTSTR lpszString,
LPVOID lpData
)
cdlgz 2006-01-09
  • 打赏
  • 举报
回复
(REGISTERWORDENUMPROC)EnumRegisterWordProc用得不对吧
改成(REGISTERWORDENUMPROC*)EnumRegisterWordProc试试
cdlgz 2006-01-09
  • 打赏
  • 举报
回复
回调函数能封装到类里,而且只能做静态函数,像线程函数一样
handsomerun 2006-01-09
  • 打赏
  • 举报
回复
试了试,没问题

cpp中
void CMyDlg::OnButton1()
{
HKL hKL = LoadKeyboardLayout("E0010411", KLF_SETFORPROCESS);
int num = ImmEnumRegisterWord(hKL, (REGISTERWORDENUMPROC)EnumRegisterWordProc, NULL, 0, NULL, NULL);


UINT ret1 = ImmEnumRegisterWord(hKL, (REGISTERWORDENUMPROC)EnumRegisterWordProc, NULL, 0, NULL, NULL);


}

UINT CALLBACK CMyDlg::EnumRegisterWordProc
(LPCTSTR lpszReading, DWORD dwStyle, LPCTSTR lpszString, LPVOID lpData)
{

return 0;
}


在.h文件中,是这样的

class CMyDlg : public CDialog
{
protected:
static UINT CALLBACK EnumRegisterWordProc
(LPCTSTR lpszReading, DWORD dwStyle, LPCTSTR lpszString, LPVOID lpData );


编译通过了
link没过,因为我没有
Coreimm.lib这个文件
linuxyf 2006-01-09
  • 打赏
  • 举报
回复
哪位能帮我在机子上编译一下,看看这到底是什么问题, 有人说这个回调函数不能封装到类里, 到底能不能, 谁能告诉我?
加载更多回复(15)

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧