博文

SDI初始化机制探密 , 你知道吗?(2006-12-15 15:25:00)

摘要: 学习MFC这么久,直到前几天才弄明白了一个长久困扰我的问题.并且是一个很重要的问题,是关于MFC的机制.下面我拿出来和大家一起共享一下,请多指教.   大家都知道,对于一个SDI,不管是新建还是打开一份文档,都会引发一系列的操作.                               而我们的SDI开始运行时,都会自动先新建一份文档.确实它跟点击”新建”菜单项的操作是相同的.那么到底是在哪里自动调用这个菜单项的操作的呢?   到处都没找到.后来无意之间,在InitInstance中看到一个奇怪的家伙:   BOOL CManageApp::InitInstance() {        AfxEnableControlContainer();          // Standard initialization        // If you are not using these features and wish to reduce the size        //  of your final executable, you should remove from the following        //  the specific initialization routines you do not need.   #ifdef _AFXDLL        Enable3dControls();         &......

阅读全文(3772) | 评论:0

VC编程小经验(3)(2006-12-09 16:52:00)

摘要:更新中:   14."ctrl+]"  组合键的使用可以帮助你快速检测出括号的配准情况。首先定位光标于 第一个括号前面,然后按下组合键,系统会自动马上找到匹配的括号,并将光标定位 于那里。否则保持不动。 应用指数:★★★★
成功率:80%   15.有时候,你想添加一个系统消息时却发现找不到,,比如是窗口消息,但在一个基于对话框的程序中却找不到。很是烦人。有办法。打开"类向导" 以后,切换到"class Info"选项卡下,在"Message Filter"列表框下选择window,而不是dialog或者其他什么就可以了。 应用指数:★★★★
成功率:80%   16.长久看了VC工作区,眼睛会疲劳,可以试着更改一下设置。方法是菜单栏   -- 工具 -- 选项,切换到"格式"选项卡即可。可以更换 字体,颜色等。   应用指数:★★★★
成功率:100%     17. 写了很多代码,然后更改,最后会发现代码一团糟,格式也不正确,看起来也不美观。有个简单的方法就是 alt+F8,只要选中要整理 的代码,然后按键,即可。   应用指数:★★★★★
成功率:100%     18.如果工作空间中有2个工程,那么每次运行一个的时候,必须设置它为活动工程(方法不在阐述)。这样很麻烦。有种简单的方法是: 右击打开“组建”工具栏,可以看见小的横杆(组合框),里面就 可以设置活动工程。 应用指数:★★★★★
成功率:100%  
  19.每次用”class wizard”来添加消息有点大材小用了,还有种简单的方法: 右击打开“向导条”工具栏(wizardBar),设置类和要处理的消息。   应用指数:★★★★★
成功率:100%......

阅读全文(3872) | 评论:0

抽屉菜单的简单实现(2006-12-09 16:47:00)

摘要:看到 QQ的抽屉,也想自己做一个,于是做了个最简单的,界面如图所示  
        这是一个基于对话框的程序,有3个按钮,有4个对话框,1个是主窗口,还有3个是子窗口,因此需要3个对话框的资源风格为:  “下层,对话框架“     下面是具体设计过程:   1.给3个子窗口(对话框)分别派生一个对话框类,名为Cmydlg1,Cmydlg2,Cmydlg3;     2.在 Cmydlg (主窗口) 中添加成员:          Cmydlg1 *dlg1;        Cmydlg2 *dlg2;        Cmydlg3 *dlg3;        int m_left;    // 按钮的左边坐标        int m_right;  // 按钮的右边坐标        int m_buttonHeight;// 按钮的高度        int m_buttonWidth; // 按钮的宽度        int m_dlgHeight;  // 子对话框的高度,而宽度与按钮应该相同        CButton m_button[3]; // 3个按钮,下面会动态创建     3.初始化   BOOL CMyDlg::OnInitDialog() {        CDialog::OnInit......

阅读全文(5011) | 评论:1

控件的实时拖动(2006-12-07 16:29:00)

摘要:由于一个小项目的需要,必须做控件的拖曳。以前还真没有想过这种问题。先来看看有没有处理消息,比如drag什么的,很遗憾没有。再来看看有没有函数,好像也没有,郁闷。没办法了。只好用绝招,自己做一个派生类把,下面我就以编辑框为例,简单说明一下拖曳的过程。 1。从CEdit派生一个类为CmyEdit。 2。添加左键处理函数:  void Cmyedit::OnLButtonDown(UINT nFlags, CPoint point)
{
          // TODO: Add your message handler code here and/or call default
          pp=point;      // pp是Cmyedit的成员变量
          SetTimer(5,10,NULL);  // 引发定时器
          CEdit::OnLButtonDown(nFlags, point);
}   void Cmyedit::OnLButtonUp(UINT nFlags, CPoint point)
{
         // TODO: Add your message handler code here and/or call default
        KillTimer(5);  // 关闭定时器
        CEdit::OnLBu......

阅读全文(3108) | 评论:1

UpdateData 探索(2006-12-03 13:44:00)

摘要:早就想写这篇文章了,一直苦于没有时间。这么好的周末我自然不会浪费,于是上来侃2句了,希望对初学者有益。   UpdateData这个函数相信大家已经了解。带有1个参数。如果参数为TRUE,表示将控件中的内容“输入”给它的关联变量。如果是FALSE,表示将关联变量的内容输入到控件中。 一     UpdateData(FALSE) 假设现在已经有一个编辑框了,并且设置了一个关联变量m_stredit。好,现在我想初始化它,让对话框一运行的时候,编辑框中就有字符了。常见的做法如下: BOOL Cmydlg::OnInitDialog() {     CDialog::OnInitDialog();      ........    m_stredit="hello,world!";   UpdateData(FALSE); ............. } 结果自然正确。后来还见过这种写法,在构造函数中初始化关联变量: Cmydlg::Cmydlg(CWnd* pParent /*=NULL*/)
 : CDialog(Cmydlg::IDD, pParent)
{
 //{{AFX_DATA_INIT(CJianyanDlg)
  // NOTE: the ClassWizard will add member initialization here
 //}}AFX_DATA_INIT
 // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_stredit="hello,world!";
} 其他什么代码也没写。奇怪,也能运行。我并没有调用UpdateData(FALSE)啊?在哪儿调用了?一行行的检查自然让我把注意力集中在了: CDialog::OnInitDialog(); 这个基类的函数到底干了些什么勾当?我要搞明白。方法是这样的: 菜单栏,编辑,在文件中查找,......

阅读全文(7407) | 评论:0

LINEDDA(1)(2006-12-03 00:53:00)

摘要:呵呵,看到这个题目你可能马上就想起了计算机图形学上的直线DDA算法把。这个函数实际上已经被winapi包含了,可以用来做动画。介绍一下函数: void WINAPI    LineDDA(int x1,int y1,int x2,int y2,LINEDDAPROC back,LPARAM l); 参数解释如下: x1,y1;//直线的起点坐标 x2,y2;//直线的终点坐标 back;//回调函数,就是通过DDA算法计算出直线上一个象素的坐标后就马上调用 l;//可传值参数 再介绍一下回调函数: typedef  void (CALLBACK *LINEDDAPROC)(int x,int y ,LPARAM l) x,y;//计算出的象素点坐标 l; //是刚才的传递参数 呵呵,有了这么多,就可以做很多事情了哦!我举一小例说明 1。利用向导生成一个基于SDI的程序。 2。在视类中响应左键单击事件: void CLineDDAView::OnLButtonDown(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default
  CClientDC dc(this);
 ::LineDDA(100,100,200,200,(LINEDDAPROC)hehe,(LPARAM)&dc);
 CView::OnLButtonDown(nFlags, point);
} 3。声明回调函数为视类的静态成员函数:  static void CALLBACK hehe(int a,int b,LPARAM l); 在源文件中定义: int a1=100,b1=100;//全局变量 void    CALLBACK      CLineDDAView::hehe(int a,int b,LPARAM l)
{
 CDC *pDC=(CDC*)l;
&n......

阅读全文(3315) | 评论:0

不容小视的坐标问题  差点翻船!(2006-12-03 00:17:00)

摘要:没事的时候做了小程序,结果出现了大问题。 情况是这样的: 是一个基于对话框的程序。首先 BOOL  Cmydlg::OnInitDialog() { ...... CRect rect1; GetWindowRect(rect1);    } 同时我也添加了一个按钮控件,处理单击事件: void Cmydlg::OnButtonClk() { CRect rect2; GetWindowRect(rect2);  } 以前我的理解是GetWindowRect获得的都是相对于屏幕坐标系的坐标,所以我猜想rect1此时不会左上角是0,0,,并且rect1==rect2,哪知道一跟踪,差点晕过去,左上角虽然不是0,但是也接近于0了,rect1也根本不等于rect2,这是怎么回事? 不明白。问了高手,才知道,原来在初始化(OnInitDialog)的时候,窗口还没有完全显示,此时用函数进行测试结果肯定不正确。后来测试的rect2才是真的屏幕坐标系上的坐标。原来是这样!好险! 但是我还有个问题没能解决。那就是rect1到底测的是什么呢?不知道,知道的告诉一下啊 下面再来谈谈MoveWindow For a top-level CWnd object, the x and y parameters are relative to the upper-left corner of the screen. For a child CWnd object, they are relative to the upper-left corner of the parent window’s client area. The MoveWindow function sends the WM_GETMINMAXINFO message. Handling this message gives CWnd the opportunity to modify the default values for the largest and smallest possible windows. If the parameters to the MoveWindow member function exceed......

阅读全文(3849) | 评论:0

如何初始化(2006-12-02 17:25:00)

摘要:1.想一下这个问题,现在在MFC的类中定义了一个成员数组,要初始化,怎么办? 比如:   本来想:int a[5]={1,2,3,4,5}; 但是定义在类中,是不能像上面这样初始化的,只能一个一个的初始化。还真是不好办。 你有好方法吗?     不过,如果是静态成员,就很好办了。如在类中的定义: static const CRect m_rcSquares[9]; //9个矩形。 初始化的语句可以写在源文件中: const CRect COXgameDlg::m_rcSquares[9]={            CRect(16,16,112,112),               CRect(128,16,224,112),               CRect(240,16,336,112),               CRect(16,128,112,224),               CRect(128,128,224,224),               CRect(240,128,336,224),               CRect(16,240,112,336),     &......

阅读全文(5432) | 评论:0

MFC中的全局函数(2006-12-02 13:14:00)

摘要:初涉MFC,你可能以为c++是一个纯面向对象的语言。天天都在和类打交道,似乎感觉缺了点什么。一天突然想添加全局函数和变量,顿时不知道该怎么办,后来查了点资料再认真思考了一下,原来很简单。下面我就简单讲讲我的心得把。   1.extern 声明法 全局函数和变量的概念在c里面最先提出来。那个时候,我们都只编写最简单的main函数,然后再加上2个调用函数,或者加上全局变量。这个时候的全局变量只针对这一个文件(.c 或者cpp)。不知道大家还记得吗?还有一个外部变量。它是应用于多源文件。方法就是使用extern对所要引用的外部变量进行声明就可以了,这样就使外部变量的作用域其他源程序文件中。现在回想起这段话,不正是和眼前的MFC多源程序相关么?     事实也正是如此。当你在MFC中想定义一个全局变量时,如在视类CmyView中定义一个全局变量 int a;可以这样做:   在CmyView的源文件的最前面加入:         int a; 如果现在想在文档类中调用,那么只需包含视类的头文件,并且在文档类的源文件中加入         extern int a ; 这样就和视类共享这样一个全局变量。 全局函数的方法也是同样,不多说明。 2.static成员法 第二种方法也很简单,只是有时候很难想到,就是定义一个静态成员函数或者变量。因为是静态的,也就是不属于任何对象,而是属于这个类,那么你就不用担心在另一个类中调用函数或者变量的时候怎样去构造一个原类的对象。呵呵,这种方法很巧妙把。 同上面那个例子: 在CmyView中加入一个静态成员变量: static int a; 记得要初始化。 然后在文档类中引用 CmyView::a 即可。 这种方法经常用于创建线程函数。因为要创建一个线程函数的话,不能使它成为成员函数,因为调用的时候还需要创建对象,不方便。这个时候用静态成员函数就很适合。 3.CWinApp派生法 就是派生一个类,继承于CWinApp,再在里面定义函数或者变量。这个为什么也可以叫做全局变量呢?如: class CmyApp::pu......

阅读全文(5373) | 评论:0

CEdit重新审视(2006-11-29 21:06:00)

摘要:一个从没想过的问题今天终于出现了!我自己都感到以外!呵呵,什么问题呢?可能你也没想过哦。即使想过,你解答了没有? 是一个聊天的程序,类似于QQ的界面。简化一点说把。(注意是简化)一个基于对话框的的程序,只有2个编辑框m_edit1,m_edit2, 还有一个是按钮。现在我要做的就是在 m_edit2中输入,然后点击按钮,内容就跑到了m_edit1中。并且每次点击后,上次 m_edit1的内容还会留下来,当然是聊天嘛,每次发送的内容要在m_edit1的最后显示。呵呵,听起来很简单哦 注意我最后一句话。如果你采用连加的话,像这样: m_edit1.GetWindowText(m_str1); m_edit2.GetWindowText(m_str2); m_str1+=m_str2; m_edit1.SetWindowText(m_str1); 内容是出现了,但是光标还在第一个位置,这样如果m_edit1是一个多行的程序,有垂直滚动条,那么就麻烦了,前面我已经说了,要求是  “每次发送的内容要在m_edit1的最后显示”,也就是要求滚动条要移动到最后,按照上面那种方法,滚动条都在上面。 怎么办哪?没有关于滚动条的函数啊。其实不是滚动条的原因,原因是光标。光标还在第一个位置啊。明白了,我们要把光标移动到最后。 于是上msdn了。找“CEdit”,“class members“,这么多函数,还不知哪个是移动光标的函数呢。一个一个的试。posfromchar,SetCaretPos ,......都不行啊,晕了。。。 正绝望呢,突然想起了久违的setsel和GetSel  我们都知道CEdit是用来选中编辑框中的内容的,它们会不会有用呢?管他呢,先 全部选中再说。 m_edit1.SetFocus(); m_edit1.SetSel(0,-1); 啊!选中了!不,我不是惊喜这个(不然我会被看贴的砍死的)。除了选中之余,光标也移动到了最后!呵呵,成功了! 再想想,还不行,差一点。这样岂不是我每次要全部选中?不好。既然选中是移动光标的话,那我干脆一不做二不休,函数照用,但是我不选,呵呵,这样写: m_edit.SetFocus(); m_edit1.SetSel(m_str1.GetLength(),m_str1.Ge......

阅读全文(4833) | 评论:0