zoukankan      html  css  js  c++  java
  • win32汇编-GDI 图形 (三)

    GDI函数全部包括在GDI32.DLL中

     include     gdi32.inc
     includelib  gdi32.lib

    1 When——指的是进行图形操作的时机,

    2 Where——指的是图形该往哪里画,

    3 How——了解了上面两个问题后,最后还要知道“如何画”,

    1 计算及刷新整个客户区的代码全部安排在WM_PAINT消息中完成

    一些函数会引发WM_PAINT消息,如UpdateWindow,InvalidateRect以及InvalidateRgn函数等。

    和WM_TIMER消息类似,WM_PAINT消息也是一个低级别的消息,虽然它不会像WM_TIMER消息一样被丢弃但Windows总是在消息循环空的时候才把WM_PAINT放入

     

    WM_PAINT消息的处理流程一般是

     

    .if     eax ==   WM_PAINT   eaxuMsg

     

            invoke   BeginPaint,hWnd,addr stPS

     

            ;刷新客户区的代码

     

            invoke   EndPaint,hWnd,addr stPS

     

            xor      eax,eax

     

            ret

    读者可以发现中间并没有调用ValidateRect来使无效区域变得有效,这是因为BeginPaint函数和EndPaint函数隐含有这个功能,如果不是以BeginPaint/EndPaint当做消息处理代码的头尾的话,那么在WM_PAINT消息返回的时候就必须调用ValidateRect函数。

     

    PAINTSTRUCT STRUCT

     

      hdc           DWORD      ?  //窗口的设备环境句柄

     

      fErase        DWORD      ?  //为非零值时,表示Windows在发送WM_PAINT消息前已经用背景色擦除了无效区域

     

      rcPaint       RECT       <>  //指定了无效区域矩形的对角顶点

     

      fRestore      DWORD      ?   //后面3个字段是Windows内部使用的,应用程序不必去理会它们。

     

      fIncUpdate    DWORD      ?

     

      rgbReserved   BYTE 32 dup(?)

     

    PAINTSTRUCT ENDS

    2/ 

    程序中常常有这种需求,就是在非WM_PAINT消息中主动绘画客户区,由于BeginPaint和EndPaint函数必须在WM_PAINT消息中使用,所以这时必须用另外的方法获取hDC,可以使用以下的方法:

     

    invoke      GetDC,hWnd      ;获取hDC

     

    ;返回值是hDC

     

    ;绘图代码

     

    invoke      ReleaseDC,hWnd      ;释放hDC

     

    当绘图对象是位图的时候,同样需要一个和位图句柄相联系的DC,这时可以用函数CreateCompatibleDC来创建一个显示表面仅存在于内存中的DC:

     

    invoke  CreateCompatibleDC,hDc

     

    参数中的hDC是用来参考的DC句柄,如果指定的参数是NULL,那么建立的DC将和当前屏幕的设置兼容,为了用CreateCompatibleDC建立的DC绘画一个位图,还需要用SelectObject函数将hDC和位图句柄联系起来。

     

    用CreateDC和CreateCompatibleDC函数建立的hDC在使用结束以后,必须用DeleteDC函数删除,注意这里不能用ReleaseDC,这个函数是和GetDC配合用的。

     

    用BeginPaint/EndPaint以及GetDC获取的hDC的使用时间不能超出本条消息,与此相比,用CreateDC以及CreateCompatibleDC建立的hDC就没有这个限制,可以在任何时刻建立它并且一直使用到不再需要为止。

    7.1.3  色彩和坐标

    1. Windows中的色彩

    可以表示的颜色总数由颜色深度决定,也就是存储每个像素所用的位数,各种显示设备可以显示的颜色总数可能大不相同,如果设备支持的颜色深度太浅,就会影响到图像的质量,会让人看起来觉得很粗糙和不自然。

    一种颜色可以分解成红、绿、蓝三原色,所以可以用红、绿、蓝3个分量的组合来表示各种颜色。

    当设备支持的颜色深度少于等于8位时(如8位(256色)、4位(16色)、2位(4色)或1位(2色)),总体位数太少,不足以用来表达3个颜色分量,这时系统建立一个色彩表,像素数据用来做索引在色彩表中获取颜色值,所以低于8位的颜色称为索引色。

    只有当颜色深度大于8位的时候,像素数据中才直接包含红、绿、蓝3个分量。当颜色深度为16位的时候,红、绿、蓝各用5位表示,剩下的1位用做属性位,实际可以表示的颜色数目为215=32 768种,16位深度的彩色又称为16位色、高彩色或增强色。当颜色深度为24位的时候,3个分量各用8位表示,实际可以表示的颜色数目为224=16 777 216种,24位深度的彩色又称为24位色、16M色或真彩色。对于人的双眼来说,超过16位的颜色就已经很难分辨了。

    在Win32的编程中,统一使用32位的整数来表示一个深度为24位的颜色,在这32位中只使用低24位,每一种原色分量占用8位,其中0~7位为红色,8~15位为绿色,16~31位为蓝色。在程序中用到一种颜色常数的时候,可以如下使用:

    mov eax,红色+绿色*100h+蓝色*10000h  ;将颜色放入eax

    当显示设备无法表示24位色的时候,Windows会自动用设备可以显示的最接近的颜色来代替它,当显示设备的颜色深度比较低的时候,可以通过函数GetNearest Color来得知一种颜色(dwColor)会被系统替换成哪种颜色:

    invoke  GetNearestColor,hDC,dwColor ;返回真正使用的颜色值

    但是当显示设备颜色深度太低的时候,经过Windows自动转换的图像可能会让人觉得很不自然,所以在有些时候,程序员可能希望预先得知设备的颜色深度,然后根据具体情况显示不同的图形。

    显示设备的颜色深度可以用以下函数获取:

        invoke  GetDeviceCapshDCPLANES

        mov     ebxdwPlanes

        invoke  GetDeviceCapshDCBITSPIXEL

        mul     ebx

        mov     dwColorDepth,eax

    第一个函数调用返回DC的色彩平面数,第二个函数调用返回每个像素的色彩位数,颜色深度最后可以通过dwPlanes乘以dwBitsPixel得到。

    2. Windows中的坐标系

    要用GDI函数绘图,就必须首先了解这些函数使用的坐标系,在默认的状态下,Windows坐标系以左上角做坐标原点,以右方当做X坐标的正方向,以下方当做Y坐标的正方向。坐标的数值用一个有符号的16位数来表示,范围从―32 768~32 767,坐标的单位为像素,如图7.3所示。这种坐标系定义方法的好处是:窗口中每一点的坐标不会因为窗口的大小改变而改变,试想一下,如果以数学中通常的表示方法,以左下角做坐标原点,那么当窗口高度被用户调整的时候,客户区中每一点的Y坐标都会变化,在具体使用中就会有诸多不便。

    但是Windows也提供了其他的一些坐标映射方法供程序员使用,可以用SetMap Mode函数来为一个DC设置新的坐标映射方法:

    invoke  SetMapModehDCiMapMode

    可以设置的参数包括坐标原点、坐标的逻辑单位和坐标的正方向等,参数中的iMapMode为新的映射方式,其可以选择的取值如表7.1所示,Windows默认使用的映射方法为MM_TEXT。

    7.1  Windows中可用的坐标映射方式

    映 射 方 法

    原    点

    逻 辑 单 位

    X 正 方 向

    Y 正 方 向

    MM_TEXT(默认方式)

    左上

    像素

    MM_HIENGLISH

    左上

    0.001英寸

    MM_LOENGLISH

    左上

    0.01英寸

    MM_HIMETRIC

    左上

    0.01毫米

    MM_LOMETRIC

    左上

    0.1毫米

    MM_TWIPS

    左上

    1/1440英寸

    MM_ISOTROPIC

    可变

    可变(x=y)

    可变

    可变

    MM_ANISOTROPIC

    可变

    可变(x!=y)

    可变

    可变

    可以看到,除了默认的MM_TEXT方式外,下面5种映射方式:MM_HIENGLISH,MM_LOENGLISH,MM_HIMETRIC,MM_LOMETRIC和MM_TWIPS采用的都是原点位于左上角、X正方向向上的映射方式,另外,它们的坐标逻辑单位是不同的。

    最后的两种映射方式MM_ISOTROPIC和MM_ANISOTROPIC提供了更灵活的选择,设置为这两种映射方式后,程序可以继续调用SetViewportOrgEx,SetViewportExtEx和SetWindowExtEx函数来自由设置坐标系的原点、逻辑单位和坐标的正方向等所有参数。在其他映射方式下的时候,不能使用这3个设置函数,这时任何对它们的调用都会被忽略。

     

     

     

     

     

  • 相关阅读:
    关于委托的一篇不错的文章(C# 中的委托和事件)
    李建忠老师的《.net框架程序设计(修订版)》电子书下载地址,超级推荐
    普通无线路由变成纯AP模式
    CLR到底是什么?是怎么工作的?
    HTTP协议的三个问题
    桌面战争——揭秘中国互联网的里程碑之战
    B2C这点事儿
    不用baidu,不用google,你有bing啊
    让.net程序脱离.NET Framework在Linux下运行
    哥乃一介光棍
  • 原文地址:https://www.cnblogs.com/xuankuwa/p/3660323.html
Copyright © 2011-2022 走看看