love in C++, live on MFC

to get ready...

C++博客 首页 新随笔 联系 聚合 管理
  47 Posts :: 0 Stories :: 97 Comments :: 0 Trackbacks

置顶随笔 #

我的新博客在

http://www.codediscuss.com
   文章指数:0  CSDN Blog推出文章指数概念,文章指数是对Blog文章综合评分后推算出的,综合评分项分别是该文章的点击量,回复次数,被网摘收录数量,文章长度和文章类型;满分100,每月更新一次。
http://www.codediscuss.com 是我的博客的新地址。还是以VC++编程为主,有mfc,英语,还有点点shareware的内容。
posted @ 2007-10-02 14:23 flyingxu 阅读(1256) | 评论 (2)编辑 收藏

2007年10月2日 #

我的新博客在

http://www.codediscuss.com
   文章指数:0  CSDN Blog推出文章指数概念,文章指数是对Blog文章综合评分后推算出的,综合评分项分别是该文章的点击量,回复次数,被网摘收录数量,文章长度和文章类型;满分100,每月更新一次。
http://www.codediscuss.com 是我的博客的新地址。还是以VC++编程为主,有mfc,英语,还有点点shareware的内容。
posted @ 2007-10-02 14:23 flyingxu 阅读(1256) | 评论 (2)编辑 收藏

2007年1月5日 #

关于几个HTML文档接口的使用探讨
http://www.vckbase.com/vckbase/vckbase10/vc/nonctrls/atlcomocx_02/1002005.htm

我觉得讲的很清楚,呵呵
posted @ 2007-01-05 00:14 flyingxu 阅读(3761) | 评论 (0)编辑 收藏

2006年8月9日 #

这个答案本来是作者卖钱的,我忘了是从那个网站下载的了,估计不全。
现在有人要,就放上来吧

http://www.cppblog.com/Files/flyingxu/ThinkinginCppExercise.rar

(未验证,可能不全,或者根本就不是答案)

posted @ 2006-08-09 00:19 flyingxu 阅读(3638) | 评论 (1)编辑 收藏

2006年7月26日 #

类似的问题见http://www.experts-exchange.com/Programming/Programming_Languages/MFC/Q_20084406.html

下面的代码,当用AfxBeginThread开始一个线程时,实际上是有内存泄漏的

for  (ii  =   0 ; ii  <   1000 ; ii ++
{
  CWinThread 
*
pWinThread; 
  pWinThread 
=
 AfxBeginThread(ThreadLBProc, NULL);
  ::Sleep(
500
);
}

UINT ThreadLBProc(LPVOID pParam)
{
  
return   0
;
}

VC输出的典型提示为:
Detected memory leaks!
Dumping objects ->
thrdcore.cpp(166) : {782} client block at 0x00425300, subtype 0, 112 bytes long.
实际上,只要看到是thrdcore.cpp(166) 的内存泄漏,基本就是同一个原因,和上面的代码一样。
解决方法:
step 1)
在线程函数中,记得写AfxEndThread();(与AfxBeginThread对应,其他的开始线程的函数,有相应的函数)
step 2)
用::WaitForSingleObject()确保线程彻底退出

step 2是比较容易忽略的,用sleep函数只能侥幸的保证线程退出,但不能确保。
posted @ 2006-07-26 19:11 flyingxu 阅读(3386) | 评论 (3)编辑 收藏

2006年7月13日 #

用VC调试程序,只要按下F12,程序就出错了,出错的代码还很奇怪,再PeekMessage中,但是只出现在调试(按F5),不出现在全速运行(Ctrl+F5),release版本也没有问题
网上的解答:
http://support.microsoft.com/kb/q130667/ F12居然就是这么定义的,ft

所以,在定义程序功能的时候,就尽量不要用到F12 ,哈
posted @ 2006-07-13 18:29 flyingxu 阅读(1944) | 评论 (0)编辑 收藏

2006年7月11日 #

我在ms的group上问了个问题http://msdn.microsoft.com/newsgroups/default.aspx?dg=microsoft.public.vc.mfc&tid=402a414c-a125-45bd-9cf4-c1819db7e3e4
in http://msdn2.microsoft.com/en-us/library/480b7kf7.aspx, it says that 
pGdiObject->DeleteTempMap()
;  // Causes compiler error

But I'm confused for a static member can be called by the object or a pointer.
Is there anything wrong of my understanding?

回答的人到蛮多,讨论的也很热烈,但都没有直接回答我的问题,我的问题是,对于静态函数,
pGdiObject->DeleteTempMap();  // Causes compiler error,
到底对不对?如果不对,就是msdn错了,不过总觉得比较奇怪,msdn不该出这样的错的
posted @ 2006-07-11 19:14 flyingxu 阅读(1302) | 评论 (3)编辑 收藏

2006年7月10日 #

csdn上难得的好文章,怕不争气的csdn网站过几天又找不到这篇文章了,我得先转一下,保存一下:
http://community.csdn.net/Expert/FAQ/FAQ_Index.asp?id=193097

Q : MFC返回的临时对象指针成因?
主要解答者: QunKangLi 提交人: QunKangLi
感谢: oldforest、yu_hl、QunKangLi
审核者: happyparrot 社区对应贴子: 查看
     A :

msdn在介绍GetDlgItem的时候,明确指出:  
The  returned  pointer  may  be  temporary  and  should  not  be  stored  for  later  use.  
如果真是这样那我不惨了!在我的一个软件中,因为常常要使切换按钮的可用与不可用以及改变按钮文字,所以我用DetDlgItem把它们存了起来,用的时候直接到数组里面取,这样的话这个软件不是犯了一个重大的错误了?可是用这么久也没出错。  
另外,它也是说可能是临时的,那一定在某种情况下不是临时的,高手能不能解释一下这个问题?  
---------------------------------------------------------------  
//    Most  Windows  objects  are  represented  with  a  HANDLE,  including  
//            the  most  important  ones,  HWND,  HDC,  HPEN,  HFONT  etc.  
//    We  want  C++  objects  to  wrap  these  handle  based  objects  whenever  we  can.  
//    Since  Windows  objects  can  be  created  outside  of  C++  (eg:  calling  
//            ::CreateWindow  will  return  an  HWND  with  no  C++  wrapper)  we  must  
//            support  a  reasonably  uniform  mapping  from  permanent  handles  
//            (i.e.  the  ones  allocated  in  C++)  and  temporary  handles  (i.e.  
//            the  ones  allocated  in  C,  but  passed  through  a  C++  interface.  
//    We  keep  two  dictionaries  for  this  purpose.    The  permanent  dictionary  
//            stores  those  C++  objects  that  have  been  explicitly  created  by  
//            the  developer.    The  C++  constructor  for  the  wrapper  class  will  
//            insert  the  mapping  into  the  permanent  dictionary  and  the  C++  
//            destructor  will  remove  it  and  possibly  free  up  the  associated  
//            Windows  object.  
//    When  a  handle  passes  through  a  C++  interface  that  doesn't  exist  in  
//            the  permanent  dictionary,  we  allocate  a  temporary  wrapping  object  
//            and  store  that  mapping  into  the  temporary  dictionary.  
//    At  idle  time  the  temporary  wrapping  objects  are  flushed  (since  you  better  
//            not  be  holding  onto  something  you  didn't  create).  
//  
 
 
在CWinThread::OnIdle里调用AfxUnlockTempMaps,AfxUnlockTempMaps会释放temporary  maps.  
 
所以不要保留GetDlgItem等返回的临时指针,可以直接保存HWND  objects,然后CWnd::FromHandle获取临时指针来用。  
 
---------------------------------------------------------------  
 
临时包装对象会在空闲时间删除.在同一函数中多次使用是没用问题的,不同函数中使用先前保存下来的指针就有可能出错,特别是对话框初使化时候存下来的指针.  
       在MFC层次上的函数使用CWnd对象,而本地Windows代码(API)使用句柄.如:当Windows系统调用一个窗口过程时将传递一个HWND参数,而MFC本身的消息机制使用CWnd类;为了更好更高效的实现,MFC需要与Windows系统合作,将句柄与CWnd对象进行关联---它用CHandleMap完成关联.  
CHandleMap有两个CMapPtrToPtr的成员变量:m_permanentMap(永久映射表,程序运行过程中对象/句柄之间的关系),m_temporaryMap(临时映射表,在消息存在的过程中才存在).永久表保存显式创建的CWnd对象,当对象创建时将在永久目录下插入一个条目,在CWnd::OnNcDestrory时删除对应条目.但是Windows有时会传入某些不是由开发人员显式创建的窗口的句柄,此时MFC会分配一个临时对象来包装这个句柄并将它们的映射保存到临时映射表中,这些临时对象会在空闲时间被删除并移走相应的临时映射表条目.类似的MFC对象与Windows句柄的映射表有:  
m_pmapHWND:                        窗口句柄与CWnd对象  
m_pampHMENU:                        菜单句柄与CMenu对象  
m_pmapHDC:                        设备环境句柄与CDC对象  
m_pmapHGDIOBJ:                        GDI句柄与CGDI对象  
m_mapHIMAGELIST:            图像链表句柄到CImageList对象  
 
当给定句柄,如HWND时,MFC简单调用CWnd*  PASCAL  CWnd::FromHandle(HWND  hWnd),  此函数内部使用CHandleMap::FromHandle(hWnd)获取相关联的CWnd对象.在CHandleMap::FromHandle(h)内部(源代码在WinHand.cpp),先使用CObject*  pObject  =  LookupPermanent(h);            if  (pObject  !=  NULL)return  pObject;    检查永久表;如永久表中不存在,使用pObject  =  LookupTemporary(h))  !=  NULL检查临时表,都不存在时,使用pTemp  =  =  m_pClass->CreateObject();if  (pTemp  ==  NULL)AfxThrowMemoryException();m_temporaryMap.SetAt((LPVOID)h,  pTemp);创建临时对象并将其插入到临时表中去,同时返回该临时对象.  
void  CHandleMap::RemoveHandle(HANDLE  h)的注释说明临时对象将在空闲时由OnIdel释放:  
           //  remove  only  from  permanent  map  --  temporary  objects  are  removed  
           //    at  idle  in  CHandleMap::DeleteTemp,  always!  
如果想不自动释放临时对象,使用void  AFXAPI  AfxLockTempMaps()/BOOL  AFXAPI  AfxUnlockTempMaps(BOOL  bDeleteTemps)进行锁定.  



posted @ 2006-07-10 23:18 flyingxu 阅读(1686) | 评论 (1)编辑 收藏

2006年7月9日 #

在mfc的group上有这样一个问题:(http://msdn.microsoft.com/newsgroups/default.aspx?dg=microsoft.public.vc.mfc&mid=1aa1eddf-7bcf-407b-84fe-234fe0975331&sloc=en-us
I need to update one class data and the view during the idle, I used this  
method 
in the Cdoc:
void CMyAppDoc::OnIdle(){

    theClass
->
Update();
    POSITION pos 
=
 GetFirstViewPosition();
    CView
* pView =
 GetNextView(pos);
    pView
->Invalidate(true
);
    pView
->
UpdateWindow();    
}


It works only when I move the mouse, what
's wrong? Z_Z
这个问题的确比较搞,要好好看mfc源码的,下面是我的回答
Nothing is wrong, I can explain it  is by design.
Please take a look at the source code of int CWinThread::Run(), in that function, IsIdleMessage() is called, and in IsIdleMessage() WM_PAINT is ignored, which means WM_PAINT will not cause OnIdle to be called, for windows think it's just a WM_PAINT message and will not change the UI.
Your UpdateWindow() only post a WM_PAINT message, the message queue is not empty but it's ignored by IsIdleMessage(), that's why.
But when you move your mouse, the message queue is filled with some WM_MOUSEMOVE and it's not ignored for the position changes. So your OnIdle() is called again.
-
My suggestion is to move your Invalidate & UpdateWindow code to somewhere else.
OnIdle()的确是个有点复杂的问题,我可能还会写几篇文章 :)
这里(http://groups.google.com/group/microsoft.public.vc.mfc/browse_thread/thread/14f20aa5ffd6994d/66b6e5949a31bfa2?lnk=st&q=AfxUnlockTempMaps&rnum=40&hl=zh-CN#66b6e5949a31bfa2)有篇文章讲的很到位
posted @ 2006-07-09 02:03 flyingxu 阅读(1392) | 评论 (1)编辑 收藏

2006年7月6日 #

调试程序的时候,一般
1)启动调试器,比如VC
2)在VC中设断点
3)操作程序,使得程序运行到断点,停下来
但是现在我遇到一个情况,希望调试的情景是这样的:双击某个文件,我的程序启动后,这个时候我想程序停下来,让我在VC中调试它。
但是,双击文件后启动的程序,是个独立的exe运行程序,肯定不是在VC的运行控制下的,VC中设置的断点不起作用的。怎么办呢?
这个时候可以在想让程序停下来的地方增加指令_asm int 3,debug下编译好。双击文件后运行这个exe,在exe运行到_asm int 3时,就会中断,而把当前的exe运行与一个新的调试器(一个新的VC进程)结合起来。接下来就像一般的调试了。
这时的调试步骤类似与:
1)程序运行
2)遇到特定条件时,_asm int 3把当前exe与一个新的调试器,比如一个新的VC进程,联系起来
3)在调试器中调试exe

:)
posted @ 2006-07-06 17:35 flyingxu 阅读(5827) | 评论 (10)编辑 收藏

2006年6月23日 #

C++编程规范中第23条中说:
If one header file won't work unless the file that includes it also includes another header, that's gauche and puts unnecessary burden on that header file's users.
呵呵,英语有点拗口,后面举的例子也都是模板的例子。我倒是遇到过一个实际的例子,简化后如下:
//a.h
class A 
{
 
int
 a;
};
 
//b.h
//注意:b.h并没有include a.h
class B 
{
 A a;
};
 
用的时候怎么用呢?比如在main.cpp中想用class B
//main.cpp
#include "a.h"
#include 
"b.h"
//
B b;
//

//do something on b
可以看到,main为了使用B,还得包含a.h,这就是上面一段英语说的:
如果一个头文件(b.h)不能工作,除非包含它(b.h)的文件(也就是main.cpp)也包含另一个头文件(a.h)...

hehe,当我第一次遇到这种情况时,想了半天也想不明白为什么我明明包含了b.h还是不能用B啊

那么,正确的写法应该是什么呢?
在类B的作者在设计B的时候,就应该想到用户只需要#include "b.h"就可以使用这个class B。所以,在b.h文件中,应该写明#include "a.h",而不是让用户在main.cpp中去include "a.h"

:)
posted @ 2006-06-23 20:56 flyingxu 阅读(1740) | 评论 (5)编辑 收藏

仅列出标题  下一页