不怕大家笑话,我通过国家水平考试高级程序员级,自认为在算法设计上没有问题,数据结构不能说精通也不会差,因为高级程序员考试对编程者的能力要求还是很高的(我自己认为),但是要命的是它还是考的是c\c++(dos环境),不考windows编程,以至于我现在连一个最基本的windows程序也不能理解,那怕是用向导建的一个什么也不会做的程序外壳,我也不能理解它是怎么回事,我曾经两次试过要过渡到windows编程,可是都没成功。(我并不是不懂c++,在VC中建个空的win32,我也能运用自如)。
于是,我想请教各位高手们,当你们刚开始学windows编
程时是怎么学的,用的是什么书(给我推荐几本也行),还用,windows是通过消息传递来工作的,这我也知道,但我看消息都是定义好的,用大写字母表达的,有没有这样的书,能够介绍一下每一种消息,和它的表达方式呢?还有,能否推荐一本详细介绍windows API的书呢?另外我想请问几个具体一点的问题,书上说windows程序是从winmain开始运行的,可是我怎么也找不到这个函数,它在哪里呢?书上还说每一个对话框类都是由其成员函数create建立的,可是我还是找不到它在哪里!我用的是VC++6.0。
于是,我想请教各位高手们,当你们刚开始学windows编
程时是怎么学的,用的是什么书(给我推荐几本也行),还用,windows是通过消息传递来工作的,这我也知道,但我看消息都是定义好的,用大写字母表达的,有没有这样的书,能够介绍一下每一种消息,和它的表达方式呢?还有,能否推荐一本详细介绍windows API的书呢?另外我想请问几个具体一点的问题,书上说windows程序是从winmain开始运行的,可是我怎么也找不到这个函数,它在哪里呢?书上还说每一个对话框类都是由其成员函数create建立的,可是我还是找不到它在哪里!我用的是VC++6.0。
解决方案 »
- 多文档程序,视图中插入listctrl和button
- 在vc中使用Flash控件, 如何知道一个flash文件已经播放结束了?
- 对话框中的CListCtrl……不能显示
- 请问现在vc程序员面试的问题一般是什莫??该注意什莫??
- 寻求CTI高手
- 初级问题-怎样才能让VC编译后的EXE程序在别人未装过VC的机子上执行?
- 值得冒这样的风险吗:我想辞职,专心地学东西,然后做底层软件的开发。
- 已有点C++基础,如何学好VC,MFC好难哦。。。
- 如何将一个CArray复制到另一个CArray动态数组中????没分了,以后补上
- static text 属性设置
- 让动态链接库只能被调用一次的方法???
- 绑定,什么是绑定,在同一台计算机上(同一个IP),但不同的端口,可以被两个不同的套接字绑定吗?
看看这篇文章,希望能对你有用
MFC程序__从TextOut说起一
该怎么开始说呢?首先这篇文章不是很标准的文章,就说说我怎么样开始真正使用VC
编程序的;然后面对的对象也不是已经在使用VC的战友们,目的或许是给还在VC门外徘徊
的,想学VC却不知如何下手一点借鉴。
仍然记得第一个知道有用的MFC函数是OnDraw(CDC *pDC),第一个使用的MFC函数是Te
xtOut(int x,int y,const CString& str)。那时候上算法分析,老师也算得上一个比较支
持VC的吧,因为他的语气让人总觉得他是比较高手的。 后来他给我们演示一个他
做的排序的算法,其实很简单,就是一个在从CView派生出来的视图里写出排序的结果,(
甚至连排序的那些数据都是写死在程序中的)。这算什么高深的VC程序啊!——当时看是
看过一些书,都是说些MFC 基础类库的,但是对这些东西都没有理性的认识,就算是这样
一个在View中写出“Hello World”来也不知道该往哪里写。这第一个TextOut(…)就写在
OnDraw函数里面,而OnDraw函数是在一个文档/视图(Doc/View)结构应用程序的xxxView.c
pp文件里面(VC->新建工程->MFC AppWizard->单个文档SDI或者多个文档MDI)。VC应用程
序向导生成的文件一大堆,没真正接触以前一看到就头疼,从这一堆文件中找到一个简单
入口点其实也挺不错的。找到没有? xxxView.cpp文件的56行,不信你看看(介绍用用Edi
tPlus)。添加TextOut后的代码如下:
void CAaaView::OnDraw(CDC* pDC)
{
CAaaDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDC->TextOut(100,100,"你好");
}
我倒,一个代码一大堆的程序只有一行是我写的,各位看客要加上些其他如cout,printf之
类的代码我也不反对,不过在这里是不会生效的,至少现在不会。生成->运行,“你好”
出来了——空白包含“你好”的地方就是CxxxView起作用的地方。然后,希望加入一系列
排版得比较好的文字,就改动一下TextOut(int x,int y,const CString& str)中x,y的数
值,x和y分别表示输入点的横坐标和纵坐标,左上角为零点,向右向下递增。前面提到的
老师的排序输出就是这样做的。
知道了这一步,我想:不会吧,难道记事本那些编辑器都是要这样做出来,然后自己加入
字符处理的代码?不是的,在应用程序向导的最后一步,有个地方可以选择Base Class,
里面有CEditView(就是记事本用的),CFormView(有一个像对话框一样的背景,可以往上面
拖控件),CHtmlView(打开网页的,自己做网页浏览器哦,当然其实还是用的IE的组件),
CListView(效果如资源管理器右边显示文件列表),CRichEditView(类似Word的输入区,可
以修改字体属性等),CScrollView(和View一样的工作区,加入了滚动条控制,做图片编辑
的时候一般用这个),CTreeView(效果如资源管理器左边树形文件列表),另外在VC++.Net
中加入了CHtmlEditView,效果和FrontPage等网页编辑软件类似。另外,在使用Doc/View
结构的时候,第四步,点击高级按钮,可以设定应用程序默认打开的文件类型和后缀名。 为了继续分解、完善TextOut程序,先说说其他相关的内容:
1. 向导生成的MFC程序的基本结构及流程。刚开始学的时候,除了找到入口点,我更
希望的是了解一个MFC程序是怎样运行起来的。随便一种类型的MFC程序(doc/view结构,对
话框),打开以工程名称命名的cpp文件(CxxxApp的实现文件),一般都在第45行左右,可
以看到CxxxApp theApp; 。这里和控制台、win32程序不同,没有特定的main函数,一个对
象就是程序的开始,这也算是面向对象程序设计的一个特征吧,原来学过一阵(VC以前)JA
VA,发现他的应用程序对象的创建直接是在对象里面创建的,VC中能不能这样呢?发现是
不行,呵呵(要是行微软还不做进VC里面去,我这个认真呆)。反正这就是一个MFC程序的
生命之源(是不是有点夸张了)。这里构造了一个应用程序的对象,从这里开始,程序就
启动了,然后是CxxxApp类中的InitInstance()函数,进行一些初始化。对话框程序的话,
这里打开一个对话框;而文档/视图程序,这里构造一些可以使用的文档/视图模板(可以
通过AddDocument(…)添加多个模板,新建文档的时候会跳出窗口选择),并打开一个对应
主窗体CMainFrame。
(1) 多文档结构:
CxxxApp(CWinApp) → CMainFrame (CMDIFrameWnd)
↓↓ ↘ 菜单IDRXX
CMultiDocTemplate(模板1) (模板2) …
↙ ↘ ↓↘
CxxxView → ← CxxxDoc ↓ CChildFrame(CMDIChildWnd)
子窗体的菜单IDR_XXXTYPE
从上面可以看到主窗体有一个菜单,每个模板也有各自的菜单(菜单是模板构造函数的一
个参数),当主窗体加载模板的时候会自动用该模板的菜单替换原来的菜单。上面括号中
是各自的基类。从资料上可以看到CxxxView和CxxxDoc是关系及其紧密的两个类,View负责
用户界面的实现(所以OnDraw函数是在View类里,而不是Doc类里),Doc负责内容的实现。
用过其它的编程工具,对VC的这个机制有种感觉是增加了不少难度。但有些人或许感觉这
种对于在整个VC框架下编程是有帮助的。仁者见仁,智者见智了。
(2). 单文档结构:
CxxxApp(CWinApp) → CMainFrame (CFrameWnd)
↓↓ ↘
CSingleDocTemplate(模板1) (模板2) …
↙ ↘ ↓↓
CxxxView → ← CxxxDoc 子窗体的菜单IDR_MAINFRAME
单文档同样可以有多个模板,每个模板又有各自的菜单,那打开一个模板,再调用其它的
模板时会出现什么情况呢?新的独立的窗口跳了出来,当然这是用新模板的窗体,界面会
不一样。另外,如果关闭新的窗口不会对旧的窗口造成什么影响,如果第一个窗口关闭了
,后面打开的所有模板的窗口也随之关闭。这是因为,第一个窗口才是主进程所在。学过
操作系统的大概都知道,除非你逃课,嘿嘿。
单文档和多文档有什么区别呢(前提没有使用多模板)?难道就是单文档只有一个客户区
(就像记事本种空白区域),多文档可以有多个客户区。当然不是,单文档,顾名思义就是
只有一个CxxxDoc对象,多文档就是有多个CxxxDoc对象。下面通过一个例子来比较一下。 做一个单文档程序,在CxxxDoc里面定义一个int nTest ,构造函数中nTest=0; 在OnNewD
ocument()函数中加入代码后如下:
BOOL CTest1Doc::OnNewDocument()//看函数就该知道新建文档的时候
{ //必须调用的
if (!CDocument::OnNewDocument())
return FALSE;
CString str;
nTest++;
str.Format("nTest=%d,表示这个Doc类用了%d次",nTest,nTest);
MessageBox(NULL,str,"测试",MB_OK);
return TRUE;
}
做一个多文档程序,在同样的位置加入同样的代码。分别点击文件左上角的新建按钮,可
以发现单文档的程序每新建一次nTest就加1,而多文档程序中nTest始终为1。这说明单文
档新建的时候并没有使用一个全新的文档Doc对象,多文档程序中的则是一个新的Doc对象
。这同时给我们一个警示,单文档中如果加载了一些内容,新建的时候必须将这些内容重
置。
(3). 对话框程序。这是向导生成的最简单的MFC程序,包含的对象只有一个CxxxApp和一个
CxxxDlg。CxxxApp和前面两个MFC类型一样,是程序启动的根本,CxxxDlg则是对应对话框
的控制类。这个对话框呢!就是生成对话框应用程序的向导结束后在VC资源编辑区处于编
辑状态的窗体。对话框窗体又是怎样和CxxxDlg类联系的呢?偏题也不能偏得太远了,有机
会后面再说。
2. VC中使用的一般是匈牙利命名法,我说还不如看看别人怎么说的,下面是CSDN论坛中
一个帖子的说法:
/**************转帖部分开始*********************/
匈牙利命名法
这个方法可能很多人都听说过,包括我在内的一些人也试图去使用它,可是还是觉得自己
的好,但是现在看来这种想法是错误的。再解释解释吧。这些符号可以多个同时使用,顺
序是先m_,(这上标记指成员变量)再指针,再简单数据类型,再其他。例如:m_lpszSt
r, 表示指向一个以0字符结尾的字符串的长指针成员变量。 a Array
b Boolean
by Byte
c Char //有符号型字符
cb Char Byte //无符号型字符(没多大用处)
cr ColorRef //颜色参考值
cx,cy Length of x,y (ShortInt) //坐标差(长度)
dw Double Word
fn Function
h Handle
i Integer
m_ Member of a class
n Short Integer
np Near Pointer
p Pointer lp Long Pointer
s String
sz String with Zero End //以字符'\0'结尾的字符串
tm Text //文本内容
w Word
x,y Coordinate //坐标 类名一般没有说明字符,例如theApp. 用在其他类中加m_就行。要注意的是:某些类也有
类似于匈牙利命名法的缩写。例如:CStatusBar m_wndStatusBar;这里的wnd表示窗口类,
但是这种命名法不是标准的匈牙利命名法的一部分。
/***************转帖部分结束*******************************/
金山词霸,或者东方快典(我常备东方快典,呵呵),尽量用函数名称代替注释,而且VC
中比较规范的是函数名称每个单词第一个字母用大写。b。类的名称特定位置包含该控件的
名称的缩写(如上面说到的类似匈牙利命名法的缩写),具体什么位置,就看着办吧!MF
C类库中都是放在最后面如CxxxView,CxxxApp等等,这里我有点奇怪为什么不用CViewXXX
,CAppXXX呢?特别是文件一大串的时候类视图和文件视图都是按照字母排序的,这样按照
特定类的类型查找将更方便一些,微软做VC的时候是怎么想的呢!各位感觉怎样。第一个
字母C好像是MFC类的特称,就和Delphi的产品一样类库都用T开头。用不用,看多了一样顺
眼。当然,为了和广大的VC程序员结为一体,老老实实按照CxxxView还是没错的。
3.TextOut是不是随便一个地方都可以用的答案是:看怎么用法。这是对只做过程程序设
计的人说的。其实了解这个函数的用法的时候是在MFC程序中都可以用它,有时候要看看是
什么效果。TextOut是CDC类中的一个函数。DC(Device Context)中文是设备上下文,这和
控制台程序中的Printf函数有类似的解释。上课的时候,老师说Printf的执行结果是将字
符串从标准输出设备中输出,而我们不用管这个设备是什么,一般来说Printf的标准输出
设备默认指向命令行模式下那个黑黑的冬冬,当然有时候不是。比如上节课操作系统老师
说的,在运行包含输出的控制台程序名后面加上 > c:\tem.txt 的管道命令,这样输出结
果就到c:\tem.txt里去了。DC也差不多,在不同的情况下有不同起作用的对象,但总的来
说,我们可以当它是一块画布,专门用来画东西的,和其他面向对象程序语言中的Canvas
是殊途同归的。所不同的是类库内容丰富程度不同,简易程度也不同。在其他面向对象语
言中也可以使用DC,不过一般不是基础类库中的CDC,而是用DC的句柄HDC(C++ Builder
5.0里面也可以用MFC编程)。在View类中OnDraw的CDC *pDC作用效果就是在客户区操作,
画图,写字等,OnPrint的CDC *pDC则效果体现在打印的纸上了。另外每一个从CWnd派生出
来的几CWnd都可以取得对应的DC,专门用来绘制对应窗体的,操作这个DC就可以在窗体上绘制东西
了。对应命令是CDC *pDC=pWnd->GetDC();,据MSDN介绍,窗口类的DC最多只能同时被调用
(GetDC)五次,所以每次使用GetDC()以后都要调用pWnd->ReleaseDC(pDC)释放调用,以免
影响其它程序调用。CClientDC是CDC的派生类,可以通过CClientDC dc(CWnd* pWnd)来直
接获得窗口DC。
好了,现在我们来继续来完善、分解上面的TextOut程序。
如果想输出的是数字该怎么办呢?在MFC中有一个很方便的字符串类CString,所以不用像
C中仔细考虑分配内存、数字到字符串转换的问题,CString通过格式化字符串函数Format
来实现各种类型数据到字符串的转换,用法和sprintf函数类似:
CString Str;
int nInt=19;float fFloat=0.3f; CString strString="hello";char p[]="hello2"
;
Str.Format("%d,%f,%s,%s",nInt,fFloat,strString,p);
::AfxMessageBox(Str);
CString对象怎么转换成其他的数据类型呢?我暂时知道的是先转换成char* p类型,然后
通过运行库(Run-Time Library)的函数来转换,一些例子如下:
CString str="3.0";
char *p=str.GetBuffer(str.GetLength()+1);
double tf=atof(p);
int ti=atoi(p);
long tl=atol(p);
TRACE("tf=%f,ti=%d,tl=%ld\n",tf,ti,tl);
str.ReleaseBuffer();
高级一点的字符串到数值的转换函数有strtol(长整型),strtod(double型)<stdlib.h
>,值得一说的是strtol可以支持不同进制字符串到整型的转换。数值转换成字符串则用_
itoa, _ltoa, _ultoa等库函数,这些函数都支持转换成不同进制格式的字符串。具体怎么
时候还是自己动手丰衣足食咯。
好了,暂时先说这些吧!说得太多,看也懒得看了。如果有必要,下次应该说说如何在不
同地方使用DC。可能比较烂,各位高手见笑了。^_^