跟我一起学图形编程

                              作者:姚明联系方式:

欢迎使用我的图形学教程。我是计算机专业的学生,对图形图像技术有浓厚的兴趣,就读期间广泛的涉及相关知识,但始终没有深入研究。原因很简单,我认为广度可以决定深度,大学期间应博学,不宜专于细节。现在毕业了,我选择了图形学作为自己深入研究的方向。

关于图形学,我也算是初学者,也许,与大家不同的是,在深入研究之前,我做了充分的知识准备,我计划从点的绘制开始,实现一套完整的三维渲染流水线。朋友们,跟我一起学吧,让我们披荆斩棘,一起攀上这座美丽的高峰!

下面,开始我们的第一步,创建一个windows下的窗口程序。

理论:

Windows程序中,在写图形用户界面时需要调用大量的标准Windows Gui函数。其实这对用户和程序员来说都有好处,对于用户,面对的是同一套标准的窗口,对这些窗口的操作都是一样的,所以使用不同的应用程序时无须重新学习操作。对程序员来说,这些Gui源代码都是经过了微软的严格测试,随时拿来就可以用的。当然至于具体地写程序对于程序员来说还是有难度的。为了创建基于窗口的应用程序,必须严格遵守规范。作到这一点并不难,只要用模块化或面向对象的编程方法即可。

下面我就列出在桌面显示一个窗口的几个步骤:

得到您应用程序的句柄(必需);

得到命令行参数(如果您想从命令行得到参数,可选);

注册窗口类(必需,除非您使用Windows预定义的窗口类,如MessageBox或dialog box;

产生窗口(必需);

在桌面显示窗口(必需,除非您不想立即显示它);

刷新窗口客户区;

进入无限的获取窗口消息的循环;

如果有消息到达,由负责该窗口的窗口回调函数处理;

如果用户关闭窗口,进行退出处理。

相对于单用户的DOS下的编程来说,Windows下的程序框架结构是相当复杂的。但是Windows和DOS在系统架构上是截然不同的。Windows是一个多任务的操作系统,故系统中同时有多个应用程序彼此协同运行。这就要求Windows程序员必须严格遵守编程规范,并养成良好的编程风格。

Windows中的文本是一个GUI(图形用户界面)对象。每一个字符实际上是由许多的像素点组成,这些点在有笔画的地方显示出来,这样就会出现字符。这也是为什么我说“绘制”字符,而不是写字符。通常您都是在您应用程序的客户区“绘制”字符串(尽管您也可以在客户区外“绘制”)。Windows下的“绘制”字符串方法和Dos下的截然不同,在Dos下,您可以把屏幕想象成85 x 25的一个平面,而Windows下由于屏幕上同时有几个应用程序的画面,所以您必须严格遵从规范。Windows通过把每一个应用程序限制在他的客户区来做到这一点。当然客户区的大小是可变的,您随时可以调整。

在您在客户区“绘制”字符串前,您必须从Windows那里得到您客户区的大小,确实您无法像在DOS下那样随心所欲地在屏幕上任何地方“绘制”,绘制前您必须得到Windows的允许,然后Windows会告诉您客户区的大小,字体,颜色和其它GUI对象的属性。您可以用这些来在客户区“绘制”。

什么是“设备环境”(DC)呢? 它其实是由Windows内部维护的一个数据结构。一个“设备环境”和一个特定的设备相连。像打印机和显示器。对于显示器来说,“设备环境”和一个个特定的窗口相连。

“设备环境”中的有些属性和绘图有关,像:颜色,字体等。您可以随时改动那些缺省值,之所以保存缺省值是为了方便。您可以把“设备环境”想象成是Windows为您准备的一个绘图环境,而您可以随时根据需要改变某些缺省属性。

当应用程序需要绘制时,您必须得到一个“设备环境”的句柄。通常有几种方法。

在WM_PAINT消息中使用call BeginPaint

在其他消息中使用call GetDC

call CreateDC建立你自己的DC

您必须牢记的是,在处理单个消息后你必须释放“设备环境”句柄。不要在一个消息处理中获得“设备环境”句柄,而在另一个消息处理中在释放它。

我们在Windows发送WM_PAINT消息时处理绘制客户区,Windows不会保存客户区的内容,它用的是方法是“重绘”机制(譬如当客户区刚被另一个应用程序的客户区覆盖),Windows会把WM_PAINT消息放入该应用程序的消息队列。重绘窗口的客户区是各个窗口自己的责任,您要做的是在窗口过程处理WM_PAINT的部分知道绘制什么和何如绘制。

您必须了解的另一个概念是“无效区域”。Windows把一个最小的需要重绘的正方形区域叫做“无效区域”。当Windows发现了一个”无效区域“后,它就会向该应用程序发送一个WM_PAINT消息,在WM_PAINT的处理过程中,窗口首先得到一个有关绘图的结构体,里面包括无效区的坐标位置等。您可以通过调用BeginPaint让“无效区”有效,如果您不处理WM_PAINT消息,至少要调用缺省的窗口处理函数DefWindowProc,或者调用ValidateRect让“无效区”有效。否则您的应用程序将会收到无穷无尽的WM_PAINT消息。

下面是响应该消息的步骤:

取得“设备环境”句柄

绘制客户区

释放“设备环境”句柄

注意,您无须显式地让“无效区”有效,这个动作由BeginPaint自动完成。您可以在BeginPaint和Endpaint之间,调用所有的绘制函数。几乎所有的GDI函数都需要“设备环境”的句柄作为参数。

内容:

下面是我们简单的窗口程序的源代码。在进入复杂的细节前,我将提纲挈领地指出几点要点:

您应当把程序中要用到的所有常量和结构体的声明放到一个头文件中,并且在源程序的开始处包含这个头文件。这么做将会节省您大量的时间,也免得一次又一次的敲键盘。您也可以定义您自己的常量和结构体,但最好把它们放到独立的头文件中。

在其它地方运用头文件中定义函数原型,常数和结构体时,要严格保持和头文件中的定义一致,包括大小写。在查询函数定义时,这将节约您大量的时间;

如果想详细系统的学习Windows编程,可以参考《windows程序设计》,

如果你的系统中没有安装VC,或不会使用VC,我准备了精简版本,只有10MB左右,无需复杂操作,也能编译本教程中的代码,生成程序,

如果你对下面的代码视如天书,那么请先看《谭浩强C语言教程》,务必熟读,

1

/**//*------------------------------------------------------------------------2  HELLOWIN.CPP -- Displays "你好, 欢迎使用YM的图形学教程!" in client area3                 (c) Charles Petzold, 19984-----------------------------------------------------------------------*/5#include67LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;89intWINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,10                   PSTR szCmdLine,intiCmdShow)11

{12staticTCHAR szAppName[]=TEXT ("HelloWin") ;13    HWND   hwnd ;14    MSG    msg ;15    WNDCLASS    wndclass ;16    wndclass.style=CS_HREDRAW|CS_VREDRAW ;17    wndclass.lpfnWndProc=WndProc ;18    wndclass.cbClsExtra=0;19    wndclass.cbWndExtra=0;20    wndclass.hInstance=hInstance ;21    wndclass.hIcon=LoadIcon (NULL, IDI_APPLICATION) ;22    wndclass.hCursor=LoadCursor (NULL, IDC_ARROW) ;23    wndclass.hbrBackground=(HBRUSH) GetStockObject (WHITE_BRUSH) ;24    wndclass.lpszMenuName=NULL ;25    wndclass.lpszClassName=szAppName ;26    RegisterClass (&wndclass);27    hwnd=CreateWindow( szAppName,//window class name28TEXT ("The Hello Program"),//window caption29WS_OVERLAPPEDWINDOW,//window style30CW_USEDEFAULT,//initial x position31CW_USEDEFAULT,//initial y position32CW_USEDEFAULT,//initial x size33CW_USEDEFAULT,//initial y size34NULL,//parent window handle35NULL,//window menu handle36hInstance,//program instance handle37NULL) ;//creation parameters38ShowWindow (hwnd, iCmdShow) ;39    UpdateWindow (hwnd) ;40while(GetMessage (&msg, NULL,0,0))41

{42          TranslateMessage (&msg) ;43          DispatchMessage (&msg) ;44    }45returnmsg.wParam ;46}47LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)48

{49    HDC            hdc ;50    PAINTSTRUCT     ps ;51    RECT          rect ;52switch(message)53

{54caseWM_PAINT:55            hdc=BeginPaint (hwnd,&ps) ;56            GetClientRect (hwnd,&rect) ;57            DrawText (hdc, TEXT ("你好, 欢迎使用YM的图形学教程!"),-1,&rect,58                   DT_SINGLELINE|DT_CENTER|DT_VCENTER) ;59            EndPaint (hwnd,&ps) ;60return0;61caseWM_DESTROY:62            PostQuitMessage (0) ;63return0;64    }65returnDefWindowProc (hwnd, message, wParam, lParam) ;66}67

分析:

看到一个简单的Windows程序有这么多行,您是不是有点想撤?但是您必须要知道的是上面的大多数代码都是模板而已,模板的意思即是指这些代码对差不多所有标准Windows程序来说都是相同的。在写Windows程序时您可以把这些代码拷来拷去,当然把这些重复的代码写到一个库中也挺好。其实真正要写的代码集中在WinMain中。这和一些C编译器一样,无须要关心其它杂务,集中精力于WinMain函数。唯一不同的是C编译器要求您的源代码有必须有一个函数叫WinMain。否则C无法知道将哪个函数和有关的前后代码链接。相对C,汇编语言提供了较大的灵活性,它不强行要求一个叫WinMain的函数。

下面我们开始分析,您可得做好思想准备,这可不是一件太轻松的活。

HELLOWIN至少呼叫了18个Windows函数。下面以它们在HELLOWIN中出现的次序列出这些函数以及各自的简明描述:

LoadIcon加载图标供程序使用。

LoadCursor加载鼠标光标供程序使用。

GetStockObject取得一个图形对象(在这个例子中,是取得绘制窗口背景的画刷对象)。

RegisterClass为程序窗口注册窗口类别。

MessageBox显示消息框。

CreateWindow根据窗口类别建立一个窗口。

ShowWindow在屏幕上显示窗口。

UpdateWindow指示窗口自我更新。

GetMessage从消息队列中取得消息。

TranslateMessage转译某些键盘消息。

DispatchMessage将消息发送给窗口消息处理程序。

PlaySound播放一个声音文件。

BeginPaint开始绘制窗口。

GetClientRect取得窗口显示区域的大小。

DrawText显示字符串。

EndPaint结束绘制窗口。

PostQuitMessage在消息队列中插入一个「退出程序」消息。

DefWindowProc执行内定的消息处理。

这些函数均在Platform SDK文件中说明,并在不同的表头文件中声明,其中绝大多数声明在WINUSER.H中。

WinMain函数共有4个参数:应用程序的实例句柄,该应用程序的前一实例句柄,命令行参数串指针和窗口如何显示。Win32没有前一实例句柄的概念,所以第二个参数总为0。之所以保留它是为了和Win16兼容的考虑,在Win16下,如果hPrevInst是NULL,则该函数是第一次运行。特别注意:您不用必须申明一个名为WinMain函数,事实上在这方面您可以完全作主,您甚至无须有一个和WinMain等同的函数。您只要把WinMain中的代码拷到GetCommandLine之后,其所实现的功能完全相同。在WinMain返回时,产生一个返回值。然后在应用程序结束时通过ExitProcess函数把该返回码传递给Windows。

1

wndclass.style=CS_HREDRAW|CS_VREDRAW ;2    wndclass.lpfnWndProc=WndProc ;3    wndclass.cbClsExtra=0;4    wndclass.cbWndExtra=0;5    wndclass.hInstance=hInstance ;6    wndclass.hIcon=LoadIcon (NULL, IDI_APPLICATION) ;7    wndclass.hCursor=LoadCursor (NULL, IDC_ARROW) ;8    wndclass.hbrBackground=(HBRUSH) GetStockObject (WHITE_BRUSH) ;9    wndclass.lpszMenuName=NULL ;10   wndclass.lpszClassName=szAppName ;11   RegisterClass (&wndclass);12

上面几行从概念上说确实是非常地简单。只要几行指令就可以实现。其中的主要概念就是窗口类(window class),一个窗口类就是一个有关窗口的规范,这个规范定义了几个主要的窗口的元素,如:图标、光标、背景色、和负责处理该窗口的函数。您产生一个窗口时就必须要有这样的一个窗口类。如果您要产生不止一个同种类型的窗口时,最好的方法就是把这个窗口类存储起来,这种方法可以节约许多的内存空间。也许今天您不会太感觉到,可是想想以前PC大多数只有1M内存时,这么做是非常有必要的。如果您要定义自己的创建窗口类就必须:在一个WINDCLASS或WINDOWCLASSEX结构体中指明您窗口的组成元素,然后调用RegisterClass或RegisterClass,再根据该窗口类产生窗口。对不同特色的窗口必须定义不同的窗口类。WINDOWS有几个预定义的窗口类,譬如:按钮、编辑框等。要产生该种风格的窗口无须预先再定义窗口类了,只要包预定义类的类名作为参数调用CreateWindow即可。

WNDCLASS中最重要的成员莫过于lpfnWndProc了。前缀lpfn表示该成员是一个指向函数的长指针。在Win32中由于内存模式是FLAT型,所以没有near或far的区别。每一个窗口类必须有一个窗口过程,当Windows把属于特定窗口的消息发送给该窗口时,该窗口的窗口类负责处理所有的消息,如键盘消息或鼠标消息。由于窗口过程差不多智能地处理了所有的窗口消息循环,所以您只要在其中加入消息处理过程即可。下面我将要讲解WNDCLASSEX的每一个成员

1

typedefstructtagWNDCLASS{2  UINT      style;3  WNDPROC   lpfnWndProc;4intcbClsExtra;5intcbWndExtra;6  HINSTANCE hInstance;7  HICON     hIcon;8  HCURSOR   hCursor;9  HBRUSH    hbrBackground;10  LPCTSTR   lpszMenuName;11  LPCTSTR   lpszClassName;12}WNDCLASS,*PWNDCLASS;1314CreateWindow( szAppName,//window class name15TEXT ("The Hello Program"),//window caption16WS_OVERLAPPEDWINDOW,//window style17CW_USEDEFAULT,//initial x position18CW_USEDEFAULT,//initial y position19CW_USEDEFAULT,//initial x size20CW_USEDEFAULT,//initial y size21NULL,//parent window handle22NULL,//window menu handle23hInstance,//program instance handle24NULL) ;//creation parameters25

注册窗口类后,我们将调用CreateWindow来产生实际的窗口。请注意该函数有11个参数。

1

HWND WINAPI CreateWindow(2  __in_opt  LPCTSTR lpClassName,3  __in_opt  LPCTSTR lpWindowName,4  __in      DWORD dwStyle,5  __inintx,6  __ininty,7  __inintnWidth,8  __inintnHeight,9  __in_opt  HWND hWndParent,10  __in_opt  HMENU hMenu,11  __in_opt  HINSTANCE hInstance,12  __in_opt  LPVOID lpParam13);14

我们来仔细看一看这些的参数:

lpClassName:(必须)。ASCIIZ形式的窗口类名称的地址。可以是您自定义的类,也可以是预定义的类名。像上面所说,每一个应用程序必须有一个窗口类。

lpWindowName:ASCIIZ形式的窗口名称的地址。该名称会显示在标题条上。如果该参数空白,则标题条上什么都没有。

dwStyle:窗口的风格。在此您可以指定窗口的外观。可以指定该参数为零,但那样该窗口就没有系统菜单,也没有最大化和最小化按钮,也没有关闭按钮,那样您不得不按Alt+F4来关闭它。最为普遍的窗口类风格是WS_OVERLAPPEDWINDOW。 一种窗口风格是一种按位的掩码,这样您可以用“or”把您希望的窗口风格或起来。像WS_OVERLAPPEDWINDOW就是由几种最为不便普遍的风格或起来的。

X,Y: 指定窗口左上角的以像素为单位的屏幕坐标位置。缺省地可指定为CW_USEDEFAULT,这样Windows会自动为窗口指定最合适的位置。

nWidth,nHeight: 以像素为单位的窗口大小。缺省地可指定为CW_USEDEFAULT,这样Windows会自动为窗口指定最合适的大小。

hWndParent: 父窗口的句柄(如果有的话)。这个参数告诉Windows这是一个子窗口和他的父窗口是谁。这和MDI(多文档结构)不同,此处的子窗口并不会局限在父窗口的客户区内。他只是用来告诉Windows各个窗口之间的父子关系,以便在父窗口销毁是一同把其子窗口销毁。在我们的例子程序中因为只有一个窗口,故把该参数设为NULL。

hMenu:WINDOWS菜单的句柄。如果只用系统菜单则指定该参数为NULL。回头看一看WNDCLASSEX结构中的lpszMenuName参数,它也指定一个菜单,这是一个缺省菜单,任何从该窗口类派生的窗口若想用其他的菜单需在该参数中重新指定。其实该参数有双重意义:一方面若这是一个自定义窗口时该参数代表菜单句柄,另一方面,若这是一个预定义窗口时,该参数代表是该窗口的ID号。Windows是根据lpClassName参数来区分是自定义窗口还是预定义窗口的。

hInstance: 产生该窗口的应用程序的实例句柄。

lpParam: (可选)指向欲传给窗口的结构体数据类型参数的指针。如在MDI中在产生窗口时传递CLIENTCREATESTRUCT结构的参数。一般情况下,该值总为零,这表示没有参数传递给窗口。可以通过GetWindowLong函数检索该值。

1

ShowWindow (hwnd, iCmdShow) ;2UpdateWindow (hwnd) ;

调用CreateWindow成功后,会返回窗口句柄。我们必须保存该值以备后用。我们刚刚产生的窗口不会自动显示,所以必须调用ShowWindow来按照我们希望的方式来显示该窗口。接下来调用UpdateWindow来更新客户区。

1

while(GetMessage (&msg, NULL,0,0))2

{3     TranslateMessage (&msg) ;4     DispatchMessage (&msg) ;5}

这时候我们的窗口已显示在屏幕上了。但是它还不能从外界接收消息。所以我们必须给它提供相关的消息。我们是通过一个消息循环来完成该项工作的。每一个模块仅有一个消息循环,我们不断地调用GetMessage从Windows中获得消息。GetMessage传递一个MSG结构体给Windows,然后Windows在该函数中填充有关的消息,一直到Windows找到并填充好消息后GetMessage才会返回。在这段时间内系统控制权可能会转移给其他的应用程序。这样就构成了Win16下的多任务结构。如果GetMessage接收到WM_QUIT消息后就会返回FALSE,使循环结束并退出应用程序。TranslateMessage函数是一个是实用函数,它从键盘接受原始按键消息,然后解释成WM_CHAR,在把WM_CHAR放入消息队列,由于经过解释后的消息中含有按键的ASCII码,这比原始的扫描码好理解得多。如果您的应用程序不处理按键消息的话,可以不调用该函数。DispatchMessage会把消息发送给负责该窗口过程的函数。

1

returnmsg.wParam

如果消息循环结束了,退出码存放在MSG中的wParam中,您可以通过把它放到eax寄存器中传给Windows目前Windows没有利用到这个结束码,但我们最好还是遵从Windows规范已防意外。

1

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

是我们的窗口处理函数。您可以随便给该函数命名。其中第一个参数hWnd是接收消息的窗口的句柄。message是接收的消息。注意message不是一个MSG结构,其实上只是一个DWORD类型数。Windows定义了成百上千个消息,大多数您的应用程序不会处理到。当有该窗口的消息发生时,Windows会发送一个相关消息给该窗口。其窗口过程处理函数会智能的处理这些消息。wParam和lParam只是附加参数,以方便传递更多的和该消息有关的数据。

1

switch(message)2

{3caseWM_PAINT:4            hdc=BeginPaint (hwnd,&ps) ;5            GetClientRect (hwnd,&rect) ;6            DrawText (hdc, TEXT ("你好, 欢迎使用YM的图形学教程!"),-1,&rect,7                   DT_SINGLELINE|DT_CENTER|DT_VCENTER) ;8            EndPaint (hwnd,&ps) ;9return0;10caseWM_DESTROY:11            PostQuitMessage (0) ;12return0;13}14returnDefWindowProc (hwnd, message, wParam, lParam) ;15

上面可以说是关键部分。这也是我们写Windows程序时需要改写的主要部分。此处您的程序检查Windows传递过来的消息,如果是我们感兴趣的消息则加以处理,处理完后,在eax寄存器中传递0,否则必须调用DefWindowProc,把该窗口过程接收到的参数传递给缺省的窗口处理函数。所有消息中您必须处理的是WM_DESTROY,当您的应用程序结束时Windows把这个消息传递进来,当您的应用程序解说到该消息时它已经在屏幕上消失了,这仅是通知您的应用程序窗口已销毁,您必须自己准备返回Windows。在此消息中您可以做一些清理工作,但无法阻止退出应用程序。如果您要那样做的话,可以处理WM_CLOSE消息。在处理完清理工作后,您必须调用PostQuitMessage,该函数会把WM_QUIT消息传回您的应用程序,而该消息会使得GetMessage返回,并在将返回值设置0,然后会结束消息循环并退回WINDOWS。您可以在您的程序中调用DestroyWindow函数,它会发送一个WM_DESTROY消息给您自己的应用程序,从而迫使它退出。

特别注意:下面讨论的是我们以后的课程的核心部分

1

HDC            hdc ;2 PAINTSTRUCT     ps ;3 RECT          rect ;4

这些局部变量由处理WM_PAINT消息中的GDI函数调用。hdc用来存放调用BeginPaint返回的“设备环境”句柄。ps是一个PAINTSTRUCT数据类型的变量。通常您不会用到其中的许多值,它由Windows传递给BeginPaint,在结束绘制后再原封不动的传递给EndPaint。rect是一个RECT结构体类型参数,它的定义如下:

1

typedefstruct_RECT{2  LONG left;3  LONG top;4  LONG right;5  LONG bottom;6}RECT,*PRECT;7

left 和top是正方形左上角的坐标。right和bottom是正方形右下角的坐标。客户区的左上角的坐标是x=0,y=0,这样对于x=0,y=10的坐标点就在它的下面。

1

hdc=BeginPaint (hwnd,&ps) ;2      GetClientRect (hwnd,&rect) ;3      DrawText (hdc, TEXT ("你好, 欢迎使用YM的图形学教程!"),-1,&rect,4                   DT_SINGLELINE|DT_CENTER|DT_VCENTER) ;5       EndPaint (hwnd,&ps) ;6

在处理WM_PAINT消息时,您调用BeginPaint函数,传给它一个窗口句柄和未初始化的PAINTSTRUCT型参数。调用成功后在eax中返回“设备环境”的句柄。下一次,调用GetClientRect以得到客户区的大小,大小放在rect中,然后把它传给DrawText。DrawText的语法如下:

1

intDrawText(2  HDC hDC,3  LPCTSTR lpString,4intnCount,5  LPRECT lpRect,6  UNIT uFormat);7

DrawText是一个高层的调用函数。它能自动处理像换行、把文本放到客户区中间等这些杂事。所以您只管集中精力“绘制”字符串就可以了。我们会在下一课中讲解低一层的函数TextOut,该函数在一个正方形区域中格式化一个文本串。它用当前选择的字体、颜色和背景色。它处理换行以适应正方形区域。它会返回以设备逻辑单位度量的文本的高度,我们这里的度量单位是像素点。让我们来看一看该函数的参数:

hdc:“设备环境”的句柄。

lpString:要显示的文本串,该文本串要么以NULL结尾,要么在nCount中指出它的长短。

nCount:要输出的文本的长度。若以NULL结尾,该参数必须是-1。

lpRect: 指向要输出文本串的正方形区域的指针,该方形必须是一个裁剪区,也就是说超过该区域的字符将不能显示。

uFormat:指定如何显示。我们可以用or把以下标志或到一块:

DT_SINGLELINE:是否单行显示。

DT_CENTER:是否水平居中。

DT_VCENTER:是否垂直居中。

结束绘制后,必须调用 EndPaint释放“设备环境”的句柄。好了,现在我们把“绘制”文本串的要点总结如下:

必须在开始和结束处分别调用BeginPaint和EndPaint;

在BeginPaint和EndPaint之间调用所有的绘制函数;

如果在其它的消息处理中重新绘制客户区,您可以有两种选择:(1)用GetDC和ReleaseDC代替BeginPaint和EndPaint;(2)调用InvalidateRect或UpdateWindow让客户区无效,这将迫使WINDOWS把WM_PAINT放入应用程序消息队列,从而使得客户区重绘。

posted on 2011-01-22 14:49 姚明 阅读(992) 评论(0)  编辑 收藏 引用 所属分类: 原创教程

利用c语言在屏幕上画出窗口,第一课:创建一个windows窗口相关推荐

  1. python:基于matplotlib在坐标轴上画出车辆路径规划示意图(箭头、中文图例)

    车辆路径规划问题的研究一般较常遇到需要画出车辆路径示意图,已知有每辆车的真实坐标序列,那么如何利用在一个空白的坐标轴上画出路径呢? 1.准备 1.1 matplotlib引入 一般情况下只引入plt就 ...

  2. 怎样固定计算机画图曲线,如何在电脑上画出固定长度的线段

    公告: 为响应国家净网行动,部分内容已经删除,感谢读者理解. 话题:如何在电脑上画出固定长度的线段回答:这个要看你采用什么软件来画线段了 既然你是用word的话,稍微有点烦:方法为:在word里搞出绘 ...

  3. c语言在屏幕上显示字母,C语言在屏幕上的显示内容

    C语言是一门通用计算机编程语言,那么大家知道C语言在屏幕上的显示内容是什么呢?下面一起来看看! 我们有两种方式从计算机获得信息:一是看屏幕上的文字.图片.视频等,二是听从喇叭发出来的声音. 让喇叭发出 ...

  4. 用c语言让屏幕显示字体,C语言在屏幕上显示内容

    C语言在屏幕上显示内容 如何使用C语言在屏幕上显示内容呢?下面百分网小编就给大家讲解一下,希望对您有所帮助! 我们有两种方式从计算机获得信息:一是看屏幕上的文字.图片.视频等,二是听从喇叭发出来的声音 ...

  5. c语言指针法实现杨辉三角,C++_C语言在屏幕上输出杨辉三角,这就是杨辉三角,也叫贾宪三 - phpStudy...

    C语言在屏幕上输出杨辉三角 这就是杨辉三角,也叫贾宪三角.这于我们现在的学习联系最紧密的是2项式乘方展开式的系数规律.如图,在贾宪三角中,第3行的第三个数恰好对应着两数和的平方公式依次下去. 杨辉三角 ...

  6. 美国总统奥巴马不仅呼吁所有人都学习编程,甚至以身作则编写代码,成为美国历史上首位编写计算机代码的总统。2014年底,为庆祝“计算机科学教育周”正式启动,奥巴马编写了很简单的计算机代码:在屏幕上画一个正

    美国总统奥巴马不仅呼吁所有人都学习编程,甚至以身作则编写代码,成为美国历史上首位编写计算机代码的总统.2014年底,为庆祝"计算机科学教育周"正式启动,奥巴马编写了很简单的计算机代 ...

  7. 计算两个数之间所有整数的和_汇编语言:输入2个0–99之间的整数,对其做乘法运算,在屏幕上显示出该乘积对应的二进制和十六进制数...

    实验要求: (1)在屏幕提示:"please input the first number(0–99): "后,输入一个0–99之间的整数. 若所输入的数不在此范围内,或输入其它字 ...

  8. cufon,在网页上画出特殊字体

    为什么80%的码农都做不了架构师?>>>    设计师们有时会使用特殊字体让网页更好看,但浏览器通常只支持Arial.Helvetica等通用字体.那么通常的解决办法就是将特殊字体做 ...

  9. 编写一个APPlet,再随机的位置上画出几个随机大小的矩形。

    编写一个APPlet,再随机的位置上画出几个随机大小的矩形.如果一个矩形的宽度小于高度,则矩形填充成亮紫色:如果矩形的宽度大于高度,则矩形填充为浅黄色:如果矩形的宽度和高度相等,则只用红色线画出矩形的 ...

最新文章

  1. keras构建卷积神经网络(CNN(Convolutional Neural Networks))进行图像分类模型构建和学习
  2. linux tcpdump monitor模式 抓不到包 解决办法
  3. blob照片显示 oracle_保存图片到oracle的blob字段,报ora-01465
  4. javascript --- 利用节点关系访问HTML元素
  5. 【jupyter notebook】低版本 python 安装jupyter及其问题解决
  6. 检测直线方法 python
  7. Opera Mobile Classic Emulator
  8. oracle 查询有字母,oracle中查询含字母的数据[正则表达式]
  9. MAC系统级鼠标手势功能软件BetterAndBetter
  10. np.random用法
  11. 流氓与骗子的斗嘴(转)
  12. 2015第二届上海国际机上内饰与翻新展览会
  13. 用计算机弹苹果手机铃声,10秒搞定,苹果iPhone手机不用电脑换铃声,这个方法真的炒鸡简单!...
  14. 2种方法,当文本框输入@自动补全邮箱后缀(特别是命名空间的引用,共三种方法)
  15. 微信提现(商户向商家转账)
  16. 将Dos文档格式转换为Unix格式
  17. 基于BootStrap仿淘宝星星商品评价案例
  18. 【windows11 技巧】win11如何关闭你要以何方式打开此文件
  19. [基于富瀚6630平台实现U盘热插拔检测并mount]
  20. 最新10款好看的英文字体免费下载

热门文章

  1. 10栋楼连一网?看思创MS5000为1978 ARTVILLAGE酒店如何组网!
  2. 解决 System can‘t start, “mtd device must be supplied“
  3. python常用代码大全-Python常用库大全
  4. php 检查磁盘,window_Win7系统中关闭检查磁盘和扫描并修复提示的方法, Win7系统关闭“检查磁盘r - phpStudy...
  5. 旅游系统(SSM框架+MySQL+Redis+VUE)后端代码
  6. [软件评测第十三期]echo回声
  7. 机器人的自述作文_机器人作文范文300字
  8. Rust腐蚀爆炸物计算、Rust火药计算器、Rust枪声模拟器
  9. Lifelong GAN: Continual Learning for Conditional Image Generation
  10. ios用的什么编译器编译_为什么编译器是您最好的朋友