zoukankan      html  css  js  c++  java
  • 30、Windows API GDI(2)

    一、GDI的几个示例与概念

    1、笔和话刷的基本操作

    示例

    画笔示例
    **************************************/
    /* 头文件 */
    #include
    <Windows.h>
    /* 函数声明 */
    void GdiOut(HDC hdc);

    // WinMain
    int WINAPI WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow
    )
    {
    HDC hdc
    = GetDC(NULL);
    GdiOut(hdc);
    ReleaseDC(NULL, hdc);
    }
    /*************************************
    * VOID GdiOut(HDC hdc)
    * 功能 演示GDI基本功能的使用
    * 参数 HDC hdc,用于显示所绘制的图像
    * 无返回值
    *************************************
    */
    VOID GdiOut(HDC hdc)
    {
    HPEN hpen, hpenOld;
    HBRUSH hbrush, hbrushOld;
    // 初始的颜色
    BYTE bRed = 0;
    BYTE bGreen
    = 0;
    BYTE bBlue
    = 0;
    // 笔的颜色 正黑
    COLORREF cPen = RGB(bRed, bGreen, bBlue);
    // 从COLORREF类型拆解颜色,设置笔刷的颜色,这里为紫偏蓝
    COLORREF cBrush = RGB(233, GetGValue(cPen),255);
    // 创建笔
    hpen = CreatePen(PS_SOLID, 10, cPen);
    // 创建笔刷
    hbrush = CreateSolidBrush(cBrush);
    // 为DC选择笔和笔刷
    hpenOld = (HPEN)SelectObject(hdc, hpen);
    hbrushOld
    = (HBRUSH)SelectObject(hdc, hbrush);
    // 绘制线条
    LineTo(hdc,500,500);
    // 使用初始的笔
    SelectObject(hdc,hpenOld);
    // 绘制矩形
    Rectangle( hdc, 200, 200, 500, 500 );
    // 释放资源
    DeleteObject(hpen);
    SelectObject(hdc, hbrushOld);
    DeleteObject(hbrush);
    }
    2DC的操作

    GetDC

    CreateDC 除了GetDC函数外CreateDC也可以获取DC的句柄。

    ReleaseDC ReleaseDC的作用是释放DC,使其他应用程序可以使用。

    DeleteDC DeleteDC的功能是释放DC的相关系统资源。

    3、颜色的表示

    COLORREF类型和RGB

    GDI中使用红、绿、蓝三原色的组合来表示颜色。使用38位的数据组合来表示颜色,称作RGB字节,可以表示0x1000000种颜色。RGBQUAD数据结构用于表示RGB颜色,也可以使用COLORREF数据类型来表示,COLORREFDWORD大小相同,RGB宏可以将颜色表示为COLORREFGetRValueGetGValueGetBValue3个宏可以将COLORREF拆解为三原色的字节。

    DC中可用的颜色信息

    使用NUMCOLORS参数,调用GetDeviceCaps API函数即可获得指定DC的颜色数量。再使用EnumObjects函数就可以列举指定DC的所有颜色的表示。

    4、字体操作

    示例

    字体示例
    **************************************/
    /* 头文件 */
    #include
    <Windows.h>
    /*************************************
    * HFONT ChooseNewFont()
    * 功能 选择字体
    *
    * 返回值 返回字体句柄
    *************************************
    */
    HFONT ChooseNewFont()
    {
    CHOOSEFONT cf;
    LOGFONT lf;
    HFONT hfont;

    // CHOOSEFONT 结构
    cf.lStructSize = sizeof(CHOOSEFONT);
    cf.hwndOwner
    = (HWND)NULL;
    cf.hDC
    = (HDC)NULL;
    cf.lpLogFont
    = &lf;
    cf.iPointSize
    = 0;
    cf.Flags
    = CF_SCREENFONTS;
    cf.rgbColors
    = RGB(0,0,0);
    cf.lCustData
    = 0L;
    cf.lpfnHook
    = (LPCFHOOKPROC)NULL;
    cf.lpTemplateName
    = (LPSTR)NULL;
    cf.hInstance
    = (HINSTANCE) NULL;
    cf.lpszStyle
    = (LPSTR)NULL;
    cf.nFontType
    = SCREEN_FONTTYPE;
    cf.nSizeMin
    = 0;
    cf.nSizeMax
    = 0;

    // 选择字体对话框
    ChooseFont(&cf);
    // 得到HFONT 返回
    hfont = CreateFontIndirect(cf.lpLogFont);
    return (hfont);
    }
    /*************************************
    * WinMain
    * 功能 选择字体,并将文字显示在界面上
    *
    *************************************
    */
    int WINAPI WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow
    )
    {
    HDC hdc
    = GetDC(NULL);

    int XIncrement = 10;
    int YStart = 50;
    TEXTMETRIC tm;
    HFONT hfntDefault, hfntChoose;
    SIZE sz;
    UINT uAlignPrev;
    LPSTR lpszString1
    = "字符串一";
    LPSTR lpszString2
    = "字符串二";
    LPSTR lpszString3
    = "字符串三";
    DWORD dwStrLen1
    = lstrlen(lpszString1);
    DWORD dwStrLen2
    = lstrlen(lpszString2);
    DWORD dwStrLen3
    = lstrlen(lpszString3);

    // 选择字体
    hfntChoose = ChooseNewFont();
    // 设置颜色
    SetBkColor(hdc,RGB(255,255,255));
    SetTextColor(hdc,RGB(
    255,0,0));
    SetBkMode(hdc,TRANSPARENT);

    // 输出字符串一
    TextOut(hdc, XIncrement, YStart, lpszString1, dwStrLen1);

    // 为字符串二设置输出位置
    GetTextExtentPoint32(hdc, lpszString1, dwStrLen1, &sz);
    XIncrement
    += sz.cx;
    GetTextMetrics(hdc,
    &tm);
    XIncrement
    -= tm.tmOverhang;
    // 改变字体
    hfntDefault = (HFONT)SelectObject(hdc, hfntChoose);
    // 输出字符串二
    TextOut(hdc, XIncrement, YStart, lpszString2, dwStrLen2);
    // 设置字符串三的输出位置
    GetTextExtentPoint32(hdc, lpszString1, dwStrLen1, &sz);
    XIncrement
    = 10;
    YStart
    += sz.cy;
    GetTextMetrics(hdc,
    &tm);
    XIncrement
    -= tm.tmOverhang;
    // 设置为默认字体
    SelectObject(hdc, hfntDefault);
    // 输出字符串三
    uAlignPrev = SetTextAlign(hdc, TA_UPDATECP);
    MoveToEx(hdc, XIncrement, YStart, (LPPOINT)NULL);
    TextOut(hdc,
    0, 0, lpszString3, dwStrLen3);
    SetTextAlign(hdc, uAlignPrev);
    // Clear
    DeleteObject(hfntChoose);
    SetBkMode(hdc, OPAQUE);
    DeleteDC( hdc );
    return 0;
    }

    遍历字体

    遍历字体
    **************************************/
    /* 头文件 */
    #include
    <Windows.h>
    #include
    <stdio.h>
    /* 函数声明 */
    BOOL CALLBACK EnumFamCallBack(LPLOGFONT , LPNEWTEXTMETRIC , DWORD , LPVOID ) ;
    DWORD ListFont(HWND hwnd);
    // main
    int main()
    {
    // 桌面DC
    ListFont(NULL);
    }
    /*************************************
    * DWORD ListFont(HWND hwnd)
    * 功能 列举指定窗口的DC的所具有的字体
    *************************************
    */
    DWORD ListFont(HWND hwnd)
    {
    // 获得DC
    HDC hdc = GetDC(hwnd);
    // 用于计数
    int aFontCount[] = { 0, 0, 0 };
    // 调用EnumFontFamilies,开始列举,

    EnumFontFamilies(hdc, (
    LPCTSTR) NULL,
    // 列举所有类型
    (FONTENUMPROC) EnumFamCallBack,// 回调函数为EnumFamCallBack
    (LPARAM) aFontCount); //传递给EnumFamCallBack的参数

    // 显示统计信息
    printf("Number of raster fonts: %d\n",aFontCount[0]);
    printf(
    "Number of vector fonts: %d\n",aFontCount[1]);
    printf(
    "Number of TrueType fonts: %d\n",aFontCount[2]);
    // 返回
    return 0;
    }

    /*************************************
    * EnumFamCallBack
    * 功能 字体列举回调函数次
    * 每列举一个字体会被调用一次
    * 参数 lplf,字体的LOGFONT结构
    * lpntm,字符的尺度属性
    * FontType,字体类型
    * lParam,通过EnumFontFamilies输入给本函数的参数,这里用于计数
    *************************************
    */
    BOOL CALLBACK EnumFamCallBack(
    LPLOGFONT lplf,
    LPNEWTEXTMETRIC lpntm,
    DWORD FontType,
    LPVOID aFontCount)
    {
    // 获得参数
    PINT aiFontCount = (PINT) aFontCount;
    // 判断字体类型,输出类型信息,并根据类型进行计数
    if (FontType & RASTER_FONTTYPE)
    {
    printf(
    " RASTER TYPE \t");
    aiFontCount[
    0]++;
    }
    else if (FontType & TRUETYPE_FONTTYPE)
    {
    printf(
    " TRUETYPE \t");
    aiFontCount[
    2]++;
    }
    else
    {
    printf(
    " VECTOR TYPE \t");
    aiFontCount[
    1]++;
    }
    // 显示字体信息
    printf("%s\tItalic = %d\n",lplf->lfFaceName,lplf->lfItalic);
    // 返回
    if (aiFontCount[0] || aiFontCount[1] || aiFontCount[2])
    return TRUE;
    else
    return FALSE;
    }

    EnumFontFamilies函数是实现列举DC中已经安装的字体的API函数;EnumFontFamilies函数指定了一个回调函数,每列举一个字体,回调函数就会被调用一次,字体的LOGFONT结构、字体的类型会作为参数输出给回调函数。

    5、绘制线条

    在绘制线条前需将线条所使用的画笔对象选择入DC。画笔对象决定了所绘制线条的颜色、宽度、样式。

    示例鼠标跟踪

    绘制线条
    **************************************/
    /* 头文件 */
    #include
    <windows.h>
    /* 预定义 */
    #define MAXGUIDESEGMENTS 1000
    #define MyAlloc(dwSize) HeapAlloc(GetProcessHeap(),0,dwSize)
    #define MyFree(lpMem) HeapFree(GetProcessHeap(),0,lpMem);
    /* 函数声明 */
    BOOL GetGuideLine(HWND, LPPOINT
    *, LPDWORD);
    BOOL ShowGuide(HDC, LPPOINT, DWORD);
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    DWORD GetLastErrorBox(HWND hWnd, LPSTR lpTitle);
    /* 全局变量*/
    HINSTANCE hInst;
    LPSTR szAppName
    = "Curves";
    LPSTR szTitle
    = "Curves Application";

    /*************************************
    * WinMain
    * 功能 创建窗口
    *************************************
    */
    int WINAPI WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
    {
    MSG msg;
    HWND hWnd;
    WNDCLASS wc;

    hInst
    = hInstance;
    // 注册窗口类
    wc.style = CS_OWNDC;
    wc.lpfnWndProc
    = (WNDPROC)WndProc;
    wc.cbClsExtra
    = 0;
    wc.cbWndExtra
    = 0;
    wc.hInstance
    = hInstance;
    wc.hIcon
    = NULL;
    wc.hCursor
    = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground
    = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName
    = NULL;
    wc.lpszClassName
    = szAppName;

    if (!RegisterClass(&wc))
    {
    GetLastErrorBox(NULL,
    "Error in RegisterClass");
    return (FALSE);
    }
    // 创建窗口
    hWnd = CreateWindow(
    szAppName,
    szTitle,
    WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT,
    0, CW_USEDEFAULT, 0,
    NULL,
    NULL,
    hInstance,
    NULL
    );

    if (!hWnd)
    {
    GetLastErrorBox(hWnd,
    "Error in CreateWindow");
    return (FALSE);
    }
    // 显示更新
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    // 消息循环
    while (GetMessage(&msg, NULL, 0, 0))
    {
    TranslateMessage(
    &msg);
    DispatchMessage(
    &msg);
    }

    return (int)(msg.wParam);

    UNREFERENCED_PARAMETER(lpCmdLine);
    }

    /*************************************
    * WndProc
    * 功能 窗口消息处理函数
    *************************************
    */
    LRESULT CALLBACK WndProc(
    HWND hWnd,
    UINT message,
    WPARAM uParam,
    LPARAM lParam)
    {
    static BOOL bOn = TRUE;
    static LPPOINT lpBlue = NULL;
    static LPPOINT lpRed = NULL;
    static DWORD dwBlue = 0;
    static DWORD dwRed = 0;
    static BOOL bOutlineOnly = FALSE;
    static BOOL bShowGuides = TRUE;
    static HPEN hpenBlue, hpenRed;

    switch (message)
    {
    case WM_CREATE:
    {
    // 获取DC
    HDC hDC = GetDC(hWnd);
    // 创建笔对象
    hpenBlue = CreatePen(PS_SOLID, 1, RGB(0,0,255));
    hpenRed
    = CreatePen(PS_SOLID, 1, RGB(255,0,0));
    }
    GetLastErrorBox(hWnd,
    "Error in WM_CREATE");
    break;

    case WM_PAINT:
    {
    PAINTSTRUCT ps;
    HDC hDC
    = BeginPaint(hWnd, &ps);
    RECT rect;
    // 将客户区绘制为白色
    GetClientRect(hWnd, &rect);
    PatBlt(hDC,
    0, 0, rect.right, rect.bottom, WHITENESS);
    // 即存在红线,又存在蓝线
    if (dwBlue && dwRed)
    {
    // 显示蓝线
    if (dwBlue && bShowGuides)
    {
    SelectObject(hDC, hpenBlue);
    ShowGuide(hDC, lpBlue, dwBlue);
    SelectObject(hDC, GetStockObject(BLACK_PEN));
    }
    // 显示红线
    if (dwRed && bShowGuides)
    {
    SelectObject(hDC, hpenRed);
    ShowGuide(hDC, lpRed, dwRed);
    SelectObject(hDC, GetStockObject(BLACK_PEN));
    }
    }
    EndPaint(hWnd,
    &ps);
    }
    break;

    case WM_LBUTTONDOWN:
    {
    HDC hDC
    = GetDC(hWnd);
    RECT rect;

    if (bOn)// 消除并画蓝线
    {
    // 将客户区填充为白色
    GetClientRect(hWnd, &rect);
    PatBlt(hDC,
    0, 0, rect.right, rect.bottom, WHITENESS);

    // 释放资源
    if (lpBlue)
    MyFree(lpBlue);
    if (lpRed)
    MyFree(lpRed);
    dwRed
    = 0;
    dwBlue
    = 0;

    // 开始跟踪鼠标移动,绘制蓝线
    SelectObject(hDC, hpenBlue);
    GetGuideLine(hWnd,
    &lpBlue, &dwBlue);
    }
    else//画红线
    {
    // 开始跟踪鼠标移动,绘制红线
    SelectObject(hDC, hpenRed);
    GetGuideLine(hWnd,
    &lpRed, &dwRed);
    }
    // 鼠标左键放开,恢复笔对象
    SelectObject(hDC, GetStockObject(BLACK_PEN));
    // 取反,在红色和蓝色间交替
    bOn = !bOn;
    }
    GetLastErrorBox(hWnd,
    "Error in WM_LBUTTONDOWN");
    break;

    case WM_DESTROY:
    // 释放资源,退出
    if (lpBlue) MyFree(lpBlue);
    if (lpRed) MyFree(lpRed);
    PostQuitMessage(
    0);
    break;

    default:
    return (DefWindowProc(hWnd, message, uParam, lParam));
    }
    return (0);
    }
    /*************************************
    * BOOL GetGuideLine(HWND hWnd, LPPOINT *lpPoint, LPDWORD lpdwNumPts)
    * 功能 跟踪鼠标,绘制鼠标轨迹
    * 参数 hWnd,窗口
    * lpPoint,用于保存点的数组,向调用函数返回
    * lpdwNumPts,返回的数组的大小
    *************************************
    */
    BOOL GetGuideLine(HWND hWnd, LPPOINT
    *lpPoint, LPDWORD lpdwNumPts)
    {
    MSG msg;
    HDC hDC
    = GetDC(hWnd);
    BOOL bFirstTime
    = TRUE;
    DWORD dwPos
    = 0;
    RECT rect;

    SetCapture(hWnd);
    // 设置鼠标捕获器
    GetClientRect(hWnd, &rect);
    // 为点数组分配空间
    *lpPoint = (LPPOINT)MyAlloc(MAXGUIDESEGMENTS * sizeof(POINT));

    for (;;)
    {
    // 过滤所有鼠标消息
    WaitMessage();
    if (PeekMessage(&msg,NULL,WM_MOUSEFIRST,WM_MOUSELAST,PM_REMOVE))
    {
    // 判断是否在客户区中
    if ((LOWORD(msg.lParam) < rect.right) && (HIWORD(msg.lParam) <

    rect.bottom))
    {
    // 是否第一次收到消息
    if (bFirstTime)
    {
    bFirstTime
    = FALSE;
    // 如果是第一次将笔的起点移动到鼠标点击的位置
    MoveToEx(hDC, LOWORD(msg.lParam), HIWORD(msg.lParam),

    NULL);
    }
    // 是否达到了最大点数
    if (dwPos < MAXGUIDESEGMENTS)
    {
    // 鼠标的移动会产生鼠标消息,每收到一次消息保存一个点


    (
    *lpPoint)[dwPos].x = LOWORD(msg.lParam);
    (
    *lpPoint)[dwPos].y = HIWORD(msg.lParam);
    // 绘制到鼠标所在的点
    LineTo(hDC, (*lpPoint)[dwPos].x, (*lpPoint)

    [dwPos].y);
    dwPos
    ++;
    }
    }
    if (msg.message == WM_LBUTTONUP)
    break;
    }
    else
    continue;
    }

    *lpdwNumPts = dwPos;
    ReleaseDC(hWnd, hDC);
    ReleaseCapture();
    DeleteDC( hDC );

    return TRUE;
    }

    /*************************************
    * BOOL ShowGuide(HDC hDC, LPPOINT lpPoints, DWORD dwNumPts)
    * 功能 根据保存的点的数组重绘曲线
    * 参数 hWnd,窗口
    * lpPoint,保存的点的数组,
    * dwNumPts,数组的大小
    *************************************
    */
    BOOL ShowGuide(HDC hDC, LPPOINT lpPoints, DWORD dwNumPts)
    {
    Polyline(hDC, lpPoints, dwNumPts);
    return TRUE;
    }

    // 显示错误信息
    DWORD GetLastErrorBox(HWND hWnd, LPSTR lpTitle)
    {
    LPVOID lpv;
    DWORD dwRv;

    if (GetLastError() == 0) return 0;

    dwRv
    = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
    FORMAT_MESSAGE_FROM_SYSTEM,
    NULL,
    GetLastError(),
    MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
    (LPSTR)
    &lpv,
    0,
    NULL);

    MessageBox(hWnd, (LPCSTR)lpv, lpTitle, MB_OK);

    if(dwRv)
    LocalFree(lpv);

    SetLastError(
    0);
    return dwRv;
    }

    二、相关API

    1、定义图形对象:

    CreatePen

    CreateSolidBrushCreateHatchBrushCreatePatternBrush系列

    2、图形对象的选择

    SeleteObject

    DC中每一类图形对象有一个“当前”图形对象(一个DC中同一时刻只能有一个画笔对象,也只能有一个画刷对象)。

    3、绘制图形和线条

    LineTo

    MoveToEx

    4、选择、设置字体

    CreateFont,CreateFontIndirect

    ChooseFont

        填充LOGFONT结构

    用于创建字体的LOGFONT结构成员较多,各成员的意义也不十分明确,在使用LOGFONT表示一个字体时,填充比较复杂。但是在程序设计时,一般可由程序来完成填充。有两种方法可供选用:一是使用ChooseFont API函数弹出选择字体选择对话由用户选择,ChooseFont函数会返回用户选择的字体所对应的LOGFONT结构。二是遍历系统中已经安装的字体,遍历程序会返回每一个字体所对应的LOGFONT结构,在得到LOGFONT结构后,直接调用CreateFontIndirect API函数就可以得到字体的句柄HFONT

    5、设置颜色

    SetTextColor

    6、输出文字

    DrawText

    TextOut

        GetTextExtentPoint32函数的功能是计算使用当前文本输出指定字符串后,输出的字符串的长和高(像素)。在使用TextOut等函数进行文字显示时,可以用于定义下次显示的文字的位置。

    GetTextMetrics函数用于获取文本的尺度信息。SetTextAlign函数可以指定DC的文本输出对齐方式。

    7、设置背景色

    SetBkMode

    8、安装删除字体

    AddFontResource

    RemoveFontResource

    9、绘制线条[3]

    直线:

    LineTo

    MoveToEx

    绘制任意曲线

    PolyBezierPolylinePolylineToPolyPolyline

    SetCapture

    ArcTo用于绘制椭圆弧线

    参考

    [1] 精通Windows API 函数、接口、编程实例

    [2] http://msdn.microsoft.com/en-us/library/dd183553%28VS.85%29.aspx

    [3] http://msdn.microsoft.com/en-us/library/dd162811%28VS.85%29.aspx

  • 相关阅读:
    存图---链式前向星
    Codeforces Round #664 (Div. 2)(A B C D)
    Go Running HDU
    Total Eclipse HDU
    Little W and Contest HDU
    2018 ICPC Asia Nanjing Regional Contest
    Codeforces Round #662 (Div. 2)(A B C D)
    Codeforces Round #661 (Div. 3)(A B C D E)
    素数判断(欧拉筛)
    网络流专题 模板 + 例题 (Going Home POJ
  • 原文地址:https://www.cnblogs.com/mydomain/p/1959794.html
Copyright © 2011-2022 走看看