博文
第十三课:重绘(2007-09-25 15:47:00)
摘要:第十三课:重绘
一、基本知识:
1. OnPaint和OnDraw函数
View的父类的OnPaint函数调用了OnDraw函数,若在子类为WM_PAINT消息添加响应函数OnPaint,OnDraw函数将不会被调用。
2. CpaintDC和
CpaintDC的构造函数中调用了BeginPaint(),析构函数中调用了EndPaint();
CclietnDC的构造函数中调用了GetDC(),析构函数中调用了ReleaseDC()。
而BeginPaint(),EndPaint()只能用于响应WM-PAINT消息,否则将会出错。
二、利用动态数组:
1. 定义结构体LINE,用于保存线的数据。
struct LINE
{
CPoint m_pt1;
CPoint m_pt2;
};
2. 在View中定义一个动态数组,保存每一根线的指针。
CPtrArray m_ptrLines;
定义两个Cpoint的成员变量,保存线的起点和终点:
CPoint m_ptOld;
CPoint m_ptNew;
3. 在View中加入WM_LBUTTONDOWN,WM_LBUTTONUP的响应函数,在OnLButtonDown中为m_ptNew赋值,
m_ptOld=point;
4. 在OnLButtonUp中加入代码:
m_ptNew=point;
CClientDC dc(this);
......
第十二课: 对话框综合应用(2007-09-25 15:45:00)
摘要:第十二课: 对话框综合应用
在第六课的基础上,我们添加功能。增加一个用于设置笔的样式和宽度的对话框,和用于设置颜色的对话框。
一、设置笔的样式和宽度的对话框
1. 在资源面板中添加一个对话框,在上面添加一个文本框用于改变笔的宽度,三个单选框用于选择笔的样式,一个组框用于画一条演示的线。完成后的对话框如下图:
2. 为对话框生成一个从Cdialog派生的类CsetDlg,将三个单选框设置为一组,分别为文本框和这组单选框设置一个捆绑变量。
UINT m_nWidth;
int m_nStyle;
在对话框的构造函数中为它们赋初值:
m_nWidth = 0;
m_nStyle = 0;
3. 为文本框添加EN_CHANGE消息的响应函数OnChangeEdit1(),这个函数将在文本框的文字发生改变时被调用。在其中加入下列代码:
UpdateData();
CPen newpen(m_nStyle,m_nWidth,RGB(0,0,255));
CclinetDC dc(this);
&nbs......
第十一课:Windows样式(2007-09-24 12:19:00)
摘要:第十一课:Windows样式
一、首先回忆一下WinMain一课中的创建一个窗口的几个步骤。
二、首先回忆一下MFC一课中程序执行的顺序。
三、修改Windows样式:
1. 在CMainFrame::PreCreateWindow中修改:
在窗口产生之前,会调用它的成员函数PreCreateWindow,此时窗口还没有产生,相当于一栋大楼修建之前,在它的设计图纸上修改它的式样,然后按照修改后的图纸去修建大楼。
a. 直接修改CREATESTRUCT:(让最大化按钮不可用)
cs.style &= ~WS_MAXIMIZEBOX; //去掉窗口的最大化按钮
b. 重新注册WNDCLASS:(修改窗口的图标及背景)
对于窗口的图标、背景等,不能直接修改。需要重新注册WNDCLASS。我们以修改图标为例,在资源面板中添加一个图标,其ID为IDI_ICON1:
i. 用AfxRegisterWndClass函数:
cs.lpszClass=::AfxRegisterWndClass(NULL,NULL,NULL, AfxGetApp()->LoadIcon(IDI_ICON1));
ii. 重新填写WNDCLASS
WNDCLASS wndClass;......
第十课:对话框之属性单(2007-09-24 12:18:00)
摘要:第十课:对话框之属性单
一、属性单
1. 属性单就是在属性对话框中常见的标签对话框,包括一个CpropertySheet和几个CpropertyPage。ClassWizard就是一个属性单,其中ClassWizard是一个CpropertySheet,而“Message Maps”,“Member Variables”,“ Automation”,“ ActiveX Event”和“Class Info”每一项是一个CpropertyPage。
2. 生成属性单:
a. 在资源面板里新建三个对话框,Caption属性改为容易区分的名字。每一个对话框对应于属性单中的一个CpropertyPage,对于CpropertyPage来说,它的样式有特殊的要求:Style是Child, Boder是Thin,确保TilteBar,Disable被选择。这些要求可以在MSDN中查“CPropertyPage, styles”得到。
b. 为每个对话框新建一个类Cpage1,Cpage2,Cpage3,基类选择CpropertyPage。
c. 将新建类的头文件加到 CxxxView的cpp中
#include "Page1.h"
#include "Page2.h"
#include "Page3.h"
d. 在资源面板里新建一个菜单,在CxxxView中添加它的处理函数,加入代码:
CPropertySheet ps;
Cpage1 pg1;
Cpage2 pg2;
Cpage3 pg3;
&......
第九课:对话框(二)(2007-09-24 12:16:00)
摘要:第九课:对话框(二)
建立一个基于对话框的应用程序,可以看到在CXxxApp的InitInstance()函数中:
CDlgaDlg dlg;
m_pMainWnd = &dlg;
应用程序启动时,必须对CXxxApp的成员变量m_pMainWnd进行赋值,否则无法运行。在单文档的工程中,我们看不到这种赋值操作,它是在
if (!ProcessShellCommand(cmdInfo))
return FALSE;
在ProcessShellCommand函数中对m_pMainWnd赋了值。
一、return false和return ture的区别:
1. 在CXxxApp的InitInstance()函数中:
return false:退出应用程序,不进入消息循环。
return ture:应用程序进入消息循环。
2. 在对话框类中的OnInitDialog()中:
return false:如果在OnInitDialog()函数中设置了某控件得到焦点,如:
GetDlgItem(IDC_EDIT1))->SetFocus();
应return false,否则上一句代码不会生效。
return ture:在OnInitDialog()函数中没有设置了某控件得到焦点,应return ture。
说明:要使对话框上的某个控件在一显示对话框,就具有焦点,还可以将该控件的
Table Order设为1。
二、在对话框中响应回车键:
在对话框中回车,会执行缺省按钮(Default Button)的函数,默认的缺省按钮是IDOK。如果没有缺省按钮,会执行对话框中的OnOK()函数。所以,在一个对话框中要控制回车键,可以采用下面的方法:
1. 在OnOK()函数中添加代码:
在对话框中添加四个文本框,我们想用户按回车键时,四个文本框依次循环得到焦点:
if(GetFocus()==GetDlgItem(IDC_EDIT4)) //如果第......
第八课:对话框(一)(2007-09-24 12:15:00)
摘要:第八课:对话框
一、概念
1.对话框可以在资源面板中的对话框编辑器中设计,添加各种控件,改变它们的外观,属性。对话框也用一个ID来标识,可以用ClassWizard生成类(从CDialog派生)来管理对话框。
1. 模态对话框:
模态对话框是主程序窗口打开的临时窗口,用于显示消息及取得用户数据,用户要关闭对话框才能恢复主窗口的工作。模态对话框可定义为局部变量
CMyDlg dlg; // CMyDlg是一个管理对话框的类,从CDialog派生
dlg.DoModal();//可以想象在此函数完成了对话框的显示,销毁操作。
注意,如果对话框中我们需要将某些变量取出,不能用
GetDlgItem(ID_..)->GetWindowText(),因为当DoMadle()返回时,对话框已经不存在了。
2.非模态对话框:
对话框不返回,可以切换到其他窗口,所以非模态对话框必须定义为全局变量或用 new产生,然后
dlg.Create(IDD_DIALOG1);
dlg.ShowWindow(SW_SHOW);
二、若你想在对话框上加几个控件,应在OnCreate()中加入代码,这时对话框刚刚产生,若想对控件操作,则应加在OnInitDialog()(若在OnCreate()会产生错误,因为子控件还不一定存在)。
注意:若你想改变主窗口的标题,应加在App的InitInstance()中,加在MainFrame和View中的PreCreateWindow()和OnCreate()中都不可以,因为当程序打开无标题文件时,主窗口标题被覆盖了。
三、对话框中的函数:
CWnd::GetDlgItem(nID); //得到指定控件临时对象的指针
CWnd::SetFocus(); //得到焦点
(Cedit*)GetDlgItem(IDC_EDIT1)->SetSel(0,3);//选择前4个字符
因为要用CEdit类中的SetSel()函数,所以要将得到指针进行类型转换。
使用前要得到焦点否则看不出显示效果。
CWnd::EnableWindow(false); //使得窗口失效
也可以采用发消息的方式实现:
GetDlgItem(I......
第七课:菜单(二)(2007-09-23 14:06:00)
摘要:第七课:菜单(二)
一、系统菜单:
1. 系统菜单是有鼠标点击应用程序图标弹出的菜单。点击系统菜单时,发出WM_SYSCOMMAND消息,可添加此消息的响应函数来进行控制。
2. 操作系统菜单:
在CMainFrame的OnCreate函数中加入代码:
CMenu *pMenu=GetSystemMenu(false);
//得到系统菜单
pMenu->RemoveMenu(pMenu->GetMenuItemCount()-1,MF_BYPOSITION);
//移除系统菜单的最后一项
pMenu->EnableMenuItem(SC_CLOSE,MF_DISABLED | MF_BYCOMMAND|MF_GRAYED);
//将系统菜单的“关闭”菜单项设置为失效,变灰
pMenu->AppendMenu(MF_STRING,1111,"HELLO");
//在系统菜单中添加一个菜单
GetSystemMenu(true);
//重置系统菜单到默认状态
二、运行时产生菜单:
在CMainFrame的OnCreate函数中加入代码:
mnu.CreatePopupMenu();
//产生一个弹出菜单,注意:在WIN2000下mnu应定义为成员变量,否则会报红框,WINNT下可以定义为局部变量
mnu.AppendMenu(MF_STRING,1111,"HELOO");
//向刚产生的弹出菜单加入一个菜单项
GetMenu()->AppendMenu(MF_POPUP,(INT)mnu.m_hMenu,"heha");
//将弹出菜单添加到主窗口的菜单上
GetMenu()->G......
第六课:菜单(一)(2007-09-23 14:05:00)
摘要:第六课:菜单(一)
一、有关菜单的一些基本知识:
1. 对于一个单文档的工程来说,菜单是在CxxxApp的Initinstance中产生的(Xxx为你的工程名字):
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CMenuDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CMenuView));
AddDocTemplate(pDocTemplate);
其中IDR_MAINFRAME是菜单的ID,我们在资源面板里可以看到,很多资源的ID都是IDR_MAINFRAME,包括菜单、工具栏、加速键、图标和字符串表,所以,一个ID可以标识多个资源。需要注意的是,工具栏是在CMainFrame的OnCreate函数中产生的:
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; &......
第五课 文本(2007-09-23 14:03:00)
摘要:第五课 文本
一、与文本有关的知识点:
1. WM_CHAR消息:
用户按动一下某个键,系统将发出WM_KEYDOWN, WM_KEYUP,并且参数中提供该键的虚拟扫描码。但有时用户按下某个键, 只想得到一条表示用户输入了某个字符的消息,TranslateMessage将WM_KEYDOWN, WM_KEYUP消息对转换成一条WM_CHAR消息,并在消息补充参数中提供该字符的编码。
2. CString 类:
在MFC中将对字符串的操作都封装在Cstring类中,用它来操作字符串特别方便。这一课我们要用到的是:
Empty(): 将字符串的内容清空。
Left(): 取字符串的左面几个字符串。
Format(): 得到一个格式化字符串,它的功能象C语言中的sprintf(); 如: CString str = "Some Data";
str.Format("%s%d", str, 123); //str现在的值是”SomData123”
二、 文字处理:
1. 在Cview类中加入WM_CHAR消息的处理函数OnChar,在其中加入代码:
CClientDC dc(this);
CString str;
dc.TextOut(0,0,str);
这时,只能打出一个字符,因为str是局部变量,将它改为成员变量:
CString m_strInput;
2. 加入自定义字体:
CFont fn;
fn.CreatePointFont(200,"楷体");
dc.SelectObject(&fn);
其中,CreatePointFont 是产生字体最简单的方法,它的第二个参数是字体的名字,具体你的系统中装了哪些字体,可以打开记事本,在其中的“格式”――“字体”中查到。
3. 设置文字颜色:
dc.SetTextColor(RGB(0,0,255));// 设置文字颜色为红色
......
第四课:画线(2007-09-22 13:00:00)
摘要:第四课:画线
一、 GDI、DC的概念
1. GDI:(Graphics Device Interfase)图形设备接口,是一个应用程序与输出设备之间的中介。一方面,GDI向应用程序提供一个与设备无关的编程环境,另一方面,它又以设备相关的格式和具体的设备打交道。
2. DC:(Device Context)设备描述表,是一种Windows数据结构。包括了与一个设备的绘制属性相关的信息。所有的绘制操作通过一个设备描述表进行,绘制线条、形状和文本的Windows API 函数都与DC有关。
二、 在Windows Application程序中画线
1. 定义两个全局变量用于记录鼠标按下的(x,y)坐标。
int nOrginX;
int nOrginY;
这两个变量如果定义为局部变量,放在Switch—Case语句中和回调函数中都将画不出线来。
2. 响应鼠标按下和鼠标抬起的消息:
在Swich中加入case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
3. 在鼠标按下时记录鼠标按下的(x,y)坐标,查MSDN得知WM_LBUTTONDOWN
lParam的低字存放x坐标,高字存放y坐标,将其取出存入nOrginX,nOrginY。
case WM_LBUTTONDOWN:
nOrginX=lParam & 0x0000ffff;
&nbs......