[顶级][复杂][richedit]顶级复杂的 richedit 乱码问题。。。吐血狂晕~~

09月 18th, 2008 by admin
Posted in VC/MFC | No Comments »

不知道大家用过Nero 刻录软件没有,我正在改里面的一个终极郁闷的问题,用尽了一切手段和方法也搞不定!
问题如下:

编辑菜单的时候 ,输入框采用richedit,创建方法如下:

bool cr = RichEditCtrl::Create(0, WS_CHILD |  (m_singleLine ? 0 : (ES_WANTRETURN | ES_MULTILINE)), Rect(-1, -1, -1, -1), parent, 1);
    if (cr) {
      SetEventMask(ENM_CHANGE | ENM_KEYEVENTS | ENM_SELCHANGE);
      SetTextMode(TM_PLAINTEXT);
      Subclass();
      return true;
    }
调入微软全拼,输入没有任何乱码问题,但是全拼输入时,输入法输入框跑到了屏幕最顶端。而且不能够使用输入法的选择词语功能。
我们这边的一位高手,找了一个参数ES_SELFIME解决了这个问题如下,

bool cr = RichEditCtrl::Create(0, WS_CHILD |ES_SELFIME|  (m_singleLine ? 0 : (ES_WANTRETURN | ES_MULTILINE)), Rect(-1, -1, -1, -1), parent, 1);
    if (cr) {
      SetEventMask(ENM_CHANGE | ENM_KEYEVENTS | ENM_SELCHANGE);
      SetTextMode(TM_PLAINTEXT);
      Subclass();
      return true;
    }
结果输入法位置一切正常了,但是输入汉字的时候会出现乱码!!! 然后我就开始了慢慢查找乱码的旅途。 结果发现
// get required length (use user-specified CR translation setting)
  GETTEXTLENGTHEX gtl;
  gtl.codepage = 1200;
  gtl.flags = GTL_NUMBYTES | ((flags & GT_USECRLF) ? GTL_USECRLF : GTL_DEFAULT);
  int size = (int)SendMessage(EM_GETTEXTLENGTHEX, (WPARAM)&gtl, 0);
  if (size <= 0)
    return size;

  wchar_t* p = new wchar_t[size];

  // get text
  GETTEXTEX gt;
  gt.cb = size * sizeof(wchar_t);
  gt.codepage = 1200;
  gt.flags = flags;
  gt.lpDefaultChar = 0;
  gt.lpUsedDefChar = 0;
  int rc = (int)SendMessage(EM_GETTEXTEX, (WPARAM)&gt, (LPARAM)p);
  buffer = String(p, rc);
  delete[] p;
  获取到的输入就是乱码
  本系统是 纯英文的vista 操作系统,软件在2005中编译,编译参数加了UNICODE
  也采用了 richedit2.0 unicode版本了
  LoadLibrary(L"RICHED32.DLL");
// LoadLibrary(L"RICHED20.DLL");
请问大家能不能帮我分析一下,我真是不尽感激。。

据说,微软输入法,输出的unicode,而全拼或智能ABC输出都是ANSI,自己转换吧

引用 2 楼 w_anthony 的回复:
据说,微软输入法,输出的unicode,而全拼或智能ABC输出都是ANSI,自己转换吧

无视我的话吧,我自己建了一个unicode工程,发现RichEdit2可以用全拼输入。
资源里面相关行就是这样简单的一句
    CONTROL        "",IDC_RICHEDIT21,"RichEdit20A",ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP,7,7,200,101

不太明白,加上ES_SELFIME 后,所有输入发都有乱码了,不是所有都是乱码,有些字乱码?有些字不是乱码?

http://msdn2.microsoft.com/en-us/library/bb774250(VS.85).aspx
具体设置成什么参数?? IMF_DUALFONT??

Tags: , , ,

[CEditView][用法][复杂]CEditView 的用法怎么那么复杂

06月 29th, 2008 by admin
Posted in VC/MFC | No Comments »

我用VC6 作一个简单文档编辑器,用单文档,使CEditView为View的基类,遇到了很多麻烦。
由于作业要求要能改变字体和使字体变色,所以我加入了菜单项来完成这个工作并invalidate,并在OnDraw 函数中做出重绘响应使字体变色,但一开始怎么也不做出反应然后我重载了OnPaint函数并调用OnDraw后才有了反映,但是,可是,刚有了反映当我用鼠标一点字的颜色有改了回去。。。。。。。。。。。。

请问各位这是怎么回事,怎么办才能出现我想要的结果呢?

控件有自己特定的消息处理和绘制方式,所以也有特定的应用范围。你的要求超出了Edit控件的功能,所以会感到处处不顺,尤其是自己绘制Edit非常麻烦,不如重新做一个。当然,用RichEdit也可以。

如果你修改字体和颜色是全部修改,就简单一些;颜色响应WM_CTLCOLOR消息设置;字体用SetFont()设置。

用CRichEditView

Tags: , , ,

[给出][方案][复杂]求助,等了很久都没有高手能给出方案的n个复杂问题,看来有些难度

05月 13th, 2008 by
Posted in VC/MFC | No Comments »

我从CWnd继承了1个类.并在SDI里的 C工程名VIEW 中添加了1个此类型的成员变量,并以子窗口的形式显示在客户区(实际上是做几个自定义控件,其他的问题解决得差不多了). 
1.这个问题让我这个从纯c上来的程序员的产生了一些困惑:如何能让这个子窗口的鼠标点击象cbutton在对话框中一样使 C工程名VIEW 中的成员函数来响应子窗口的电击呢?我看了cbotton的源代码,可还是没搞清所以然(也许是做在消息循环函数里了,要重载那个什么proc函数吗);后来我又想用发送自定义消息的方式来模仿WM_COMMAND,但是考虑到效率和资源问题我放弃了.后来打算在这个类中保存指向上层类的指针 C*VIEW *,但是初始化时发现类型不匹配(MYCWND::C*VIEW *无法指向C*VIEW,MYCWND是C*VIEW中的一个成员变量,不大确切的说).最后我模仿C*VIEW::getdocument()解决这问题,在函数中保存指针并返回指针。但感觉不大稳妥,不知道各位高手遇到这种问题一般是如何处理的呢?(尤其是这种一个类CLASS high的某个成员变量是一个class low类型,在这个成员变量中要调用上层high中的方法,最好能有高手帮忙指点下这个)
2.我想实现这个子窗口可以用鼠标拖动边框来改变窗口大小,但是没有这方面的资料.不知道哪位能不吝赐教.本来打算自己写个method,可是发现还真有难度(比如说如何显示窗口改变时要画的虚线,这需要在c*view中(客户区)画,这个超难搞).而且万一在此过程中鼠标甚至移出了客户区怎么办.setcapture+clip裁剪也都不容易解决,不知道有没有现成的method(本来cwnd非子窗口本身就可以的) 
3. 我想实现这个子窗口以不同的透明度来显示的method,底色透明,里面显示的字和边框不透明。打算把客户区的底层图象弄出来做gdi混色,可是如果这个子窗口下面又有另一个子窗口怎么办(比如有两个这个类的对象的子窗口,在z方向上有重叠),还是不象透明的.另外把c*view::onpaint里画的东西弄出来,做混色在进行GDI贴图.我发现不知道为什么我从cwnd里继承来的这个类的onpaint会被不停的调用,不清楚为什么(并没有什么东西在它的窗口上移来移去,猜是取底色造成的),造成资源极大消耗.并且如果真的有两个子窗口z方向重叠,上面的窗口形状发生变化,而下面的窗口漏出来的部分得不到刷新,这个该如何处理呢?
4.我想使这个窗口里的文字有联接效果,即类似 点击带下划线的文字 可以弹出个带有图片和解释性文字的子窗口。(这些文字是用户以一定格式输入的,所以位置是随即的。当显示文字较多的时候还需要上下滚动的,括号里这部分还好做)还有最好能放大显示鼠标所指向的一行文字。记得似乎有个什么tooltip类,但是没资料也不知道合适不,并且似乎那个类只是能做控件提示

请各位高手赐教赐教吧,这里多谢了!
我=了n久,一个问题的答案也没有呢,急啊,9命啊!

感谢ls的回复
1.但是发完消息,再由系统回调那不是效率很差吗(比直接调用多了好几个步骤)?你的意思是这是MFC的标准调用格式吗?但如果不是子窗口的问题呢,比如就是两个类之间函数的调用呢?
class low
{methodlow()};
class high
{methodhigh();
low objectlow;}
需要从methodlow中调用methodhigh,怎么干呢?
2.class CkJ : public CWnd{}就是这样而已,不是对话框啊。ResourceView(资源)中什么也没有啊,如何设置这个属性呢,有相关函数吗?把我逼疯了,最近我响应了mousemove,lbuttondown,lbuttonup3个函数勉强搞定了,但是绘不了虚框,直接就把窗口拉伸了:movewindow(,true)
3.codes让我delete了,修改了很多未必能运行了,大致就是这个意思吧。调试的时候发现onpaint一直在被调用,程序运行时一直停留在其中设置的断点上(断点在下面函数的第一行)
//DEL void CkJ::OnPaint() 
//DEL {
//DEL  //再配合把onerasebkgnd函数取消掉就ok了但是
//不知道为什么会一直调用这个函数分析了一下大概是影响了背景的绘制
//DEL  CClientDC mydc(this); // device context for painting
//DEL  CFont* m_pFont;
//DEL  CRect rect=m_myrect;//m_myrect是我定义在CkJ类里的一个CRect,保存了相对客户区的本窗口位置
//DEL  CBitmap* m_pBitmap=NULL;
//DEL  HBITMAP hBitmap,hOldBitmap;
//DEL  HDC hMemDC;
//DEL  // TODO: Add your message handler code here
//DEL  //dc.SetBkMode(TRANSPARENT);直接这样搞不灵
//DEL  if(m_figure)//这个参数也定义在类里,标志了窗口是椭圆还是方形
//DEL  {//如果是椭圆就要看到客户区的底色,但是混色什么的还没做,这个关键代码大部分都是抄的
//DEL  CPaintDC dc(superstratum());
//DEL  hBitmap=CreateCompatibleBitmap(dc,rect.Width(),rect.Height());
//DEL  hMemDC=CreateCompatibleDC(dc);
//DEL  hOldBitmap=(HBITMAP)SelectObject(hMemDC,hBitmap);
//DEL  BitBlt(hMemDC,0,0,rect.Width(),rect.Height(),dc,rect.left,rect.top,SRCCOPY);
//DEL  hBitmap=(HBITMAP)SelectObject(hMemDC,hOldBitmap);
//DEL  if (!m_pBitmap)
//DEL  m_pBitmap=new CBitmap;
//初始化位图,用指针的意思是打算把这个保存在类里,可以用别的方法来随着客户区图象的变化而变化,不过还没实现呢
//DEL  m_pBitmap->CreateCompatibleBitmap(&dc,rect.Width(),rect.Height());
//DEL  m_pBitmap->Attach(hBitmap);
//DEL  CDC memDC;
//DEL  memDC.CreateCompatibleDC(&mydc); 
//DEL  memDC.SelectObject(m_pBitmap); 
//DEL  memDC.StretchBlt(0, 0, rect.Width(),rect.Height(), &mydc, 0, 
//DEL  0, rect.Width(),rect.Height(), SRCCOPY);//保存 rect.leftrect.top
//DEL  memDC.DeleteDC();
//DEL  DeleteDC(hMemDC);
//DEL  m_pFont=superstratum()->GetFont();//获得窗口或对话框的字体 
//DEL  DeleteDC(dc);
//DEL  /*//SetBitmapMode(ODA_DRAWENTIRE,0);绘制按键*/
//DEL  }
//DEL  else
//DEL  {//方形就画个边框
//DEL  RECT rect=m_myrect;
//DEL  rect.top=0;rect.bottom=rect.bottom-m_myrect.top; 
//DEL  rect.left=0;rect.right=rect.right-m_myrect.left; 
//DEL  mydc.Draw3dRect(&rect,RGB(128,128,128),RGB(192,192,192));
//DEL  rect.top=rect.top+1;rect.bottom=rect.bottom-1; 
//DEL  rect.left=rect.left+1;rect.right=rect.right-1; 
//DEL  mydc.Draw3dRect(&rect,RGB(0,0,0),RGB(255,255,255));/*//*/
//DEL  }
//DEL  // Do not call CWnd::OnPaint() for painting messages
//DEL }
对这种实现 方式 我觉得非常不满意,能提供点更理想的代码吗?
4.能给详细讲讲吗,看不懂啊。Notify函数我就没用过
谢谢了

1、用SendMessage是直接调用窗口函数,比PostMessage响应要快。在Windows中各种功能都要经过很多函数中间处理,对于UI操作而言,这些中间处理所需的时间是可以忽略不计的。Windows的运行机制就是这样,能满足应用的需要就好。
2、窗体设置WS_SIZEBOX风格。
3、如果你设置断点调试,调试时需要在VC窗口与程序窗口间来回切换,每次切换到程序窗口都要刷新窗口,所以会执行OnPaint函数,所以看起来是一直重复执行OnPaint。
4、Notify是控件的属性,不是函数,在资源视图中设置。

回楼上个,1好像不对吧,SendMessge的时候还是要经过消息处理的,调试的时候在消息响应函数中看函数堆栈都是窗口的消息处理函数。
objectlow创建的时候一般都可以设置一个parent或者Owner,在objectlow中GetParent()或者GetOwen就能得到ObjectHigh的窗口指针,强制转换一下就可以直接调用函数了。
3的话用::AlphaBlend从底向上一层层绘制就可以了(可以设置透明度)。

1.楼上的办法不错,
2.cnzdgs,的答案不错,可以了
3.不是那样的,即使直接运行,也会发现子窗口在闪,光标一进入就变成漏斗状(调试的时候我也让他们各占屏幕的一部分了,平铺开了)
4.说了资源视图中什么也没有啊,在create里设置行吗?宏是怎么写的啊?设置这个属性管什么用啊。

回4楼,我说的意思是:SendMessage会直接调目标窗口的WindowProc,不经过消息循环,并不是不经过消息处理;而PostMessage是要经过消息循环的,所以SendMessage比PostMessage要快一些。

4、资源视图里面选中Static控件,查看其属性,其中有一项名称为Notify,具有这个风格的Static控件在Click时会向其父窗口发送WM_NOTIFY消息,你在其父窗口响应WM_NOTIFY消息即可。如果用Create创建,要添加的风格是SS_NOTIFY。

3.能讲讲::AlphaBlend函数怎么用吗,尤其是最后一个参数
4.谁能提供点类似的源代码吗?关于文字位置的计算的和随鼠标位置移动的提示框
谢谢

帮顶
UP
JF

3.我自己搜索到了,而且需要+上这样一行
#pragma comment(lib,"msimg32.lib")
4.的确有点复杂了,自己想办法慢慢搞吧。另外还得实现魔法表情,都不是易事。
这样就结帖散分了.

Tags: , ,