现在的位置: 首页 > 综合 > 正文

《白话 Windows 编程》第一篇 看透 Windows 第二章 GUI的世界(二) 在何时何处画

2013年10月05日 ⁄ 综合 ⁄ 共 5036字 ⁄ 字号 评论关闭
文章目录

第一篇 看透 Windows

GUI的世界() 在何时何处画

 

上一章我们讲到,在Windows的世界里,我们所看到的一切,都是“画”出来的。并且,我们大胆地在Windows的桌面画了一个红叉。画红叉似乎很爽,不过那个程序更像是一个恶作剧。只是用来证明我们可以画。这一章,我们将要学习如何“正经地”画。

每一个“正经地”的Windows应用程序,往往都是相似的,它们只在合适的时机,合适的位置上画需要的东西。我们首先来看看合适的位置是哪里。

 

2.1 在自己的窗口上画

 

我们说过,在Windows世界里,有无数的窗口(请复习第一章).现在,让我们也来制造一个窗口——通过CB,这是一件再容易不过的事了。

 

2.1.1 准备工作:创建一个窗口

 

同时在学习《白话 C++》的学员注意了,我们在《白话 C++》里,经常创建“控制台工程”,就是那个“黑黑的”的窗口。但在《白话 Windows编程》,我们更多的是以如下步骤创建一个正常的Windows应用程序工程。提醒您不要顺手就来一个控制台工程,否则,你会永远找不到“窗口”。

 

运行 C++ Builder 6,菜单:File | New | Appication。 CB6为我们新建一个空白的Windows程序工程(Project)并且自动生成了一个表单(Form)。我们知道,当程序运行之后,这个表单就被称为窗口(Window)。(如果你对这些及后面一些CB相关操作不熟,请复习《白话C++》的第二章)。

(对于CB5,在菜单File里,可以直接到的New Application。)

 

个工程很重要,马上保存工程!按一下Ctrl + Shift + S 。建议在磁盘上建立一个专门的文件夹来保存这个工程。比如,建立:bhwin/ls2/prj1/ 这样层次的文件夹。至于CPP文件名和工程名字,我都只是取默认的Unit1.cppProject1.bpr

 

2.1.2 观察一个窗口的蛛丝马迹!

2.1.2.1 第一个问题

没错,这一小节里,我们将像一个神探一样去观察一个窗口,并且提出一个个问题。撕开一匹布,最难的在于撕开最开始的一个口子,下面的一个个问题,就是我们撕裂Windows面纱的第一道口子。希望你能有一付好眼力。

 

保存之后,我们还是什么代码也不必写,直接按F9,编译,运行。在我的电脑上,显示了一个窗口。就是设计时的那个表单Form1。为了不占用太大版面,我把窗口拉得很小。

(图一:一个“光秃秃”的窗口)

 

这是一个光秃秃的窗口……这真的是一个“光秃秃”的窗口吗?仔细看这个窗口,你能发现什么?有个同学特深沉,他说看出这窗口上隐含着一幅3维立体图,并且他建议大家最好用“斗鸡眼”的方式来观察………拷!真是太夸张了,有这样的学生,我觉得大家不要叫我老师,还是叫我“大师”吧。

事实上,这个窗口并非空无一物,它有一个标题栏,标题是:Form1,在右方,还有三个小按钮,分别表示“最小化”、“最大化”、“关闭”……听到这里,你们千万不要准备退学啊!虽然这些你们早就知道,可是我们的第一个问题也出来了:

你有没有想过,标题栏,及窗口边框等,它们也是画出来的!可是,它们是由谁画出来的呢?

 

第一个问题:窗口默认的图形元素,是谁在为我们画的呢?

 

2.1.2.2 第二个问题

 

退出 Form1,我们在该表单上放一个Button(按钮)。

 

首先,在CB的“Standard”页(也就是第一页),找到按钮控件(TButton):

Standard页上 TButton 控件)

鼠标选中图示中有个“OK”的按钮,然后在当前表单上放置一个按钮,尽量放在表单的中间

(在表单上放置一个按钮)

 

双击Button1,出现代码编辑窗口,输入以下代码(黑体部分):

 

void __fastcall TForm1::Button1Click(TObject *Sender)

{

   //设置当前客户区的画笔(Pen)

   Canvas->Pen->Color = clRed;  //画笔的颜色为红色(Red)

   Canvas->Pen->Width = 10;     //画笔的粗细

 

   //开始画叉啦,需要画两笔,

   //这是第一笔:左上到右下

   Canvas->MoveTo(0,0); //把画笔移到(Move to)坐标0,0处,即 客户区的原点

   Canvas->LineTo(ClientWidth,ClientHeight);  //从当前位置画一条线到客户区的右下角。

 

   //第二笔:右上到左下:

   Canvas->MoveTo(ClientWidth,0); 

   Canvas->LineTo(0,ClientHeight);

}

//---------------------------------------------------------------------------
 

同样是画一个叉,和第一章在屏幕上相比,这里的代码省去了不少。这是因为当我们在一个自己生成的窗口上作画时,很多东西都由CB默认提供了。比如:“画布(Canvas)”,还有当前客户区的长宽:ClientWidth,ClientHeight(Client即客户的意思)MoveTo是“移动到…”,LineTo是“画线到…”这两个函数在上一章我们用过了。

 

学员会问了:老师你怎么知道变量Canvas,ClientWidth,ClientHeight;又怎么知道函数MoveTo,LineTo?嗯,这些东东你们很快也会知道它们的出处,但现在不是解释这些的时候。白话 C++的课程不是到了结构了吗?很快后面要学习“类”的知识,只有在学习了“类”的基础上,我们才可能去解释这一切。

 

言归正传,我们保存工程,按F9,编译,执行。然后按一下Button1,结果如下:

 

(图二:在客户区上画叉)

按完Button1后,千万什么也不要动,不过我猜想,你很可能已经动了什么了,没关系,再按一次Button1就是,保证你看到的图和上面的图一个样。

然后我们还是来仔细观察这个窗口!看到什么了吗?红叉“经过”了按钮,可是竟然没有“画过”按钮的表面。这是为什么?

再者,我们是从窗口的坐标原点(0,0)起笔,你注意了吗?这个坐标原点,是在窗口的左上角,而不是我们中学学笛卡尔坐标系的左下角。另外,这个绘图区域,并不位于标题栏之内,而是紧挨在标题栏之下。这就说明了,在默认情况下,我们是无法在标题上画画的。

 

第二个问题:窗口在绘画时,Windows是如何决定它要在哪里画,不在哪里画?

 

2.1.2.3 第三个问题

 

继续我们的福尔摩斯之旅!

再按一次Button1,保证那个红叉的完好。然后,我来拖一个别的窗口(比如你聊天用的QQ窗口什么的),小心地“擦过”带叉窗口的右下角……看:

 

(我拖着WinAMP的窗口,“擦过”Form1)

擦过之后:

(擦过之后,红叉短了一腿)

我们发现,另外一个窗口,居然像个“橡皮擦”一样,擦去了我在Form1这个窗口上的画的红叉的一部分。

 

再做一个试验,还是先按一个Button1画出红叉,然后小心翼翼地用鼠标在窗口边缘拉大窗口,你会发现此时红叉不受损伤。但是如果我们把窗口先缩小,然后再拉回原来大小,这时会发现,红叉又有一部分消失了。

 

第三个问题: 在窗口上画的内容,为什么会被“擦除”?

 

2.2 在需要的时

 

所有三个问题,我都没准备回答。当你学完课程,这些问题必将不再是问题。

 

如果程序还在运行着,关闭它,回到CB。

 

在Form1表单上,选中那个Button1,然后删除它(没错,我们不要它了)。

 

鼠标单击一下Form1,用以确保选中Form1本身,然后在控件属性窗口,选Event(事件)页;最后找到OnPaint这一行,如图:

(找到OnPaint事件)

在OnPaint右边的编辑框内,双击鼠标,或者按下Ctrl + 回车键。进入OnPaint事件响应函数的代码编辑处。


//---------------------------------------------------------------------------

void __fastcall TForm1::FormPaint(TObject *Sender)

{

 

}

//---------------------------------------------------------------------------

(Form1 的 OnPaint 事件响应函数)

(小心,这时候,你千万不要——没错,是不要——存盘,不然,CB会因为这个事件响应函数是空的,而自动删除它。)

然后,我们把前面Button1的OnClick函数里的代码,拷贝到FormPaint函数体内:


//---------------------------------------------------------------------------

void __fastcall TForm1::FormPaint(TObject *Sender)

{

   //设置当前客户区的画笔(Pen)

   Canvas->Pen->Color = clRed;  //画笔的颜色为红色(Red)

   Canvas->Pen->Width = 10;     //画笔的粗细

 

   //开始画叉啦,需要画两笔,

   //这是第一笔:左上到右下

   Canvas->MoveTo(0,0); //把画笔移到(Move to)坐标0,0处,即 客户区的原点

   Canvas->LineTo(ClientWidth,ClientHeight);  //从当前位置画一条线到客户区的右下角。

 

   //第二笔:右上到左下:

   Canvas->MoveTo(ClientWidth,0); 

   Canvas->LineTo(0,ClientHeight);

}

//---------------------------------------------------------------------------

(代码Copy自前面Button1OnClick)
 

这时再存盘。

确保你把代码都拷对了吗?如果你是网页上拷来的,那有时会夹带一个汉字的空格,这样就会编译不过去。不管如何,按下F9键,跑跑吧。

(又是一个红叉)

又是一个红叉,但这回,你再用别的窗口去擦除,你会发现这个红叉擦不掉了。

不过,当你调整该窗口的大小……发现什么?咦世界有些乱套:

(将窗口拉小再拉大,红叉乱掉了)

此时要想恢复红叉,最直接的方法是把该窗口最小化,再恢复。你试试,并找找其它方法。

 

或许还有很多疑问,但关于“红叉”,我们的课程完了,下面要做的,算是一个扩展。

 

2.3 Hello Windows

 

Canvas 不仅可以用来画画,也可以用来写字。严格地讲,在Windows这个一切都是画出来的世界里,写字何尝不是涂鸦?当然,Windows不会发神经到让我一笔一划“画”出字来。在Windows的安装目录下,有一个Fonts(字体)目录,里面放了很多字体。所谓的字体,就是事先建立如何画出某个字来的信息。有了字体,我们可以很轻松的在窗口上写字。

 

去掉前面FormPaint函数体内的代码,换成以下几句:


//---------------------------------------------------------------------------

void __fastcall TForm1::FormPaint(TObject *Sender)

{

   Canvas->Font->Color = clGreen; //画布的字体的颜色=绿色

   Canvas->Font->Size = 24;  //画布的字体的大小=24 (你现在看的课程,字体大小是9)

  

   Canvas->TextOut(10,10,"你好,Windows世界!");

}

//---------------------------------------------------------------------------

(更改 FormPaint里的代码,让我们向Windows世界问个好。)

按F9后,运行结果如图:

(呵呵,Windows,老朋友了。)

 

(也许,有些人对Windows没什么感情?如果你愿意,你可以把这句话改为“安红,俺想你!”,我知道你做得到。)

 

这节课就到这里吧。记住,更精采,更实用的Windows编程世界,在后面等着我们。

抱歉!评论已关闭.