GDI drawing of windows programming -- experiment 3-1

GDI Drawing for Windows Programming – Experiment 3-1

1. Experiment name

Experiment 3-1 GDI drawing experiment


2. Purpose of the experiment

  1. Understand the role of the device context in drawing

  2. Master the creation of drawing tools, and understand the relationship between drawing tools and the device environment

  3. Master the drawing steps and the use of drawing functions


3. Experimental steps and methods

  1. Modify the window code in Experiment 2, and add the drawing code in the window processing function: respond to the WM_PAINTmessage, follow the drawing steps, use the BeginPaint method to obtain the device environment handle, create a colored pen and brush with a certain style, and select Enter the device environment, and draw ellipses, rectangles and other graphics on the window. At this time, the brushes and brushes created and selected into the device environment will act on the drawn graphics, and finally delete the brushes and brushes, and use EndPaint to release the device environment. Debug and run to observe the effect of the program.

  2. On the basis of the first question, modify the code, use the GetDC/ReleaseDC method to obtain/release the device environment in the keyboard key message (WM_KEYDOWN), and realize the original drawing operation. Compile and run, drag and minimize the window, and then restore the window to see what problems occur, and consider the reason in conjunction with the ppt of the big class.

  3. Use GDI to draw a game interface, as shown in the figure below. Among them, the green part on the left is the game control panel. There are two buttons or text boxes on it to record the player’s name, score, etc., and the right is a game content panel similar to a chessboard. The window cannot be maximized or resized. Note: Multiple line segments in the game panel can be drawn repeatedly; for the type of window, you can query the style parameter of CreateWindow in MSDN.


4. Code implementation

#pragma comment(lib, "User32.lib")
#pragma comment(lib, "kernel32.lib")
#pragma comment(lib, "Gdi32.lib")

#include <windows.h>
#include <wingdi.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    
    
  static TCHAR szAppName[] = TEXT("NueXini");
  HWND hWnd;
  MSG msg;
  WNDCLASS wndclass;

  wndclass.style = CS_HREDRAW | CS_VREDRAW;
  wndclass.lpfnWndProc = WndProc;
  wndclass.cbClsExtra = 0;
  wndclass.cbWndExtra = 0;
  wndclass.hInstance = hInstance;
  wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  wndclass.lpszMenuName = NULL;
  wndclass.lpszClassName = szAppName;

  if (!RegisterClass(&wndclass))
  {
    
    
    MessageBox(NULL, TEXT("Error"), szAppName, MB_ICONERROR | MB_OK);
    return 0;
  }

  hWnd = CreateWindow(
      szAppName,
      szAppName,
      WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, // 状态条 包括标题栏 最小化按钮 菜单
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      750, // 窗口大小 width
      700, // 窗口大小 height
      NULL,
      NULL,
      hInstance,
      NULL);
  ShowWindow(hWnd, iCmdShow);
  UpdateWindow(hWnd);

  while (GetMessage(&msg, NULL, 0, 0))
  {
    
    
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

  return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    
    
  HDC hdc;
  PAINTSTRUCT ps;
  RECT rect;

  HGDIOBJ hPen, hOldPen, hBrush, hOldBruch;

  switch (message)
  {
    
    
          
  case WM_KEYDOWN:
    hdc = GetDC(hwnd);
    GetClientRect(hwnd, &rect);

    TextOut(hdc, 0, 10, _text, strlen(_text));

    ReleaseDC(hwnd, hdc);
    return 0;

  case WM_SIZE:
    GetClientRect(hwnd, &rect);
    return 0;

  case WM_PAINT:
    hdc = BeginPaint(hwnd, &ps);
    GetClientRect(hwnd, &rect);

    // 外边框
    hPen = CreatePen(PS_SOLID, 5, RGB(142, 202, 142));
    hOldPen = SelectObject(hdc, hPen);
    // 矩形内部
    hBrush = CreateSolidBrush(RGB(90, 150, 90));
    hOldBruch = SelectObject(hdc, hBrush);

    // 绘制绿色圆角矩形
    RoundRect(hdc, 40, 50, 200, 600, 10, 20);
    // 释放
    DeleteObject(hOldBruch);
    DeleteObject(hOldPen);

    // 外边框
    hPen = CreatePen(PS_SOLID, 3, RGB(180, 118, 119));
    hOldPen = SelectObject(hdc, hPen);
    // 矩形内部
    hBrush = CreateSolidBrush(RGB(160, 100, 100));
    hOldBruch = SelectObject(hdc, hBrush);
    // 绘制两个红色矩形在绿色矩形内部
    RoundRect(hdc, 50, 450, 190, 480, 10, 20);
    RoundRect(hdc, 50, 500, 190, 530, 10, 20);
    // 释放
    DeleteObject(hOldBruch);
    DeleteObject(hOldPen);

    // 绘制右边那个棋盘
    hPen = CreatePen(PS_SOLID, 3, RGB(255, 177, 177));
    hOldPen = SelectObject(hdc, hPen);
    hBrush = CreateSolidBrush(RGB(255, 130, 130));
    hOldBruch = SelectObject(hdc, hBrush);
    RoundRect(hdc, 210, 50, 700, 600, 10, 20);
    DeleteObject(hOldBruch);
    DeleteObject(hOldPen);

    // 绘制竖线
    hPen = GetStockObject(BLACK_PEN);
    hOldPen = SelectObject(hdc, hPen);
    for (size_t i = 1; i < 14; i++)
    {
    
    
      MoveToEx(hdc, 210 + (i * 35), 50, NULL);
      LineTo(hdc, 210 + (i * 35), 600);
    }

    // 绘制横线
    for (size_t i = 1; i < 15; i++)
    {
    
    
      MoveToEx(hdc, 210, 50 + (i * 37), NULL);
      LineTo(hdc, 700, 50 + (i * 37));
    }
    // 释放
    DeleteObject(hOldPen);

    EndPaint(hwnd, &ps);
    return 0;

  case WM_DESTROY:
    PostQuitMessage(0);
    return 0;
  }
  return DefWindowProc(hwnd, message, wParam, lParam);
}


5. Thinking questions

Query MSDN, learn how to use the Polygon function, draw a yellow five-pointed star, and then try to draw a five-star red flag. Pay attention to the appearance of the five-pointed red flag, where each corner of each five-pointed star is strictly the same, and each small five-pointed star is facing the big five-pointed star, so there should be strict calculations in your program to control the size and position, not random Set some values.

  • Code
#pragma comment(lib, "User32.lib")
#pragma comment(lib, "kernel32.lib")
#pragma comment(lib, "Gdi32.lib")

#include <windows.h>
#include <wingdi.h>
#include <cmath>

#define PI 3.1415926

void CalculateStarPosition(POINT *stars, size_t nCount, size_t r, size_t angle, POINT BigStar);

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
    
    
  static TCHAR szAppName[] = TEXT("NueXini");
  HWND hWnd;
  MSG msg;
  WNDCLASS wndclass;

  wndclass.style = CS_HREDRAW | CS_VREDRAW;
  wndclass.lpfnWndProc = WndProc;
  wndclass.cbClsExtra = 0;
  wndclass.cbWndExtra = 0;
  wndclass.hInstance = hInstance;
  wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  wndclass.lpszMenuName = NULL;
  wndclass.lpszClassName = szAppName;

  if (!RegisterClass(&wndclass))
  {
    
    
    MessageBox(NULL, TEXT("Error"), szAppName, MB_ICONERROR | MB_OK);
    return 0;
  }

  hWnd = CreateWindow(
      szAppName,
      szAppName,
      WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      CW_USEDEFAULT,
      NULL,
      NULL,
      hInstance,
      NULL);
  ShowWindow(hWnd, iCmdShow);
  UpdateWindow(hWnd);

  while (GetMessage(&msg, NULL, 0, 0))
  {
    
    
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

  return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    
    
  HDC hdc;
  PAINTSTRUCT ps;
  RECT rect;

  HGDIOBJ hPen, hOldPen, hBrush, hOldBrush;

  // 把左上角矩形宽分为15份,高分为10份
  size_t flagWidth = 450 / 15;
  size_t flagHeight = 300 / 10;
  POINT stars[5] = {
    
    0};

  // 第1颗
  POINT BigStar1 = {
    
    (LONG)flagWidth * 5, (LONG)flagHeight * 5};
  CalculateStarPosition(stars, 5, flagHeight * 3, 90, BigStar1);
  POINT star1[5] = {
    
    stars[0], stars[2], stars[4], stars[1], stars[3]};

  // 第2颗
  POINT BigStar2 = {
    
    (LONG)flagWidth * 10, (LONG)flagHeight * 2};
  CalculateStarPosition(stars, 5, flagHeight, 70, BigStar2);
  POINT star2[5] = {
    
    stars[0], stars[2], stars[4], stars[1], stars[3]};

  // 第3颗
  POINT BigStar3 = {
    
    (LONG)flagWidth * 12, (LONG)flagHeight * 4};
  CalculateStarPosition(stars, 5, flagHeight, 120, BigStar3);
  POINT star3[5] = {
    
    stars[0], stars[2], stars[4], stars[1], stars[3]};

  // 第4颗
  POINT BigStar4 = {
    
    (LONG)flagWidth * 12, (LONG)flagHeight * 7};
  CalculateStarPosition(stars, 5, flagHeight, 90, BigStar4);
  POINT star4[5] = {
    
    stars[0], stars[2], stars[4], stars[1], stars[3]};

  // 第5颗
  POINT BigStar5 = {
    
    (LONG)flagWidth * 10, (LONG)flagHeight * 9};
  CalculateStarPosition(stars, 5, flagHeight, 70, BigStar5);
  POINT star5[5] = {
    
    stars[0], stars[2], stars[4], stars[1], stars[3]};

  switch (message)
  {
    
    

  case WM_SIZE:
    GetClientRect(hwnd, &rect);
    return 0;

  case WM_PAINT:
    hdc = BeginPaint(hwnd, &ps);
    GetClientRect(hwnd, &rect);

    // 红色画刷
    hBrush = CreateSolidBrush(RGB(255, 0, 0));
    hOldBrush = SelectObject(hdc, hBrush);
    // 创建3:2矩形
    Rectangle(hdc, 0, 0, 900, 600);
    DeleteObject(hOldBrush);
    // 把矩形分为四个相等的矩形
    MoveToEx(hdc, 0, 300, nullptr);
    LineTo(hdc, 900, 300);

    MoveToEx(hdc, 450, 0, nullptr);
    LineTo(hdc, 450, 600);

    // 绘制横线
    for (size_t i = 0; i < 10; i++)
    {
    
    
      MoveToEx(hdc, 0, flagHeight * i, nullptr);
      LineTo(hdc, 450, flagHeight * i);
    }
    // 绘制竖线
    for (size_t i = 0; i < 15; i++)
    {
    
    
      MoveToEx(hdc, flagWidth * i, 0, nullptr);
      LineTo(hdc, flagWidth * i, 300);
    }

    // 绘制
    hBrush = CreateSolidBrush(RGB(255, 255, 0));
    hOldBrush = SelectObject(hdc, hOldBrush);
    hPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 0));
    hOldPen = SelectObject(hdc, hPen);
    SetPolyFillMode(hdc, WINDING);

    Polygon(hdc, star1, 5);
    Polygon(hdc, star2, 5);
    Polygon(hdc, star3, 5);
    Polygon(hdc, star4, 5);
    Polygon(hdc, star5, 5);

    DeleteObject(hOldPen);
    DeleteObject(hOldBrush);

    EndPaint(hwnd, &ps);
    return 0;

  case WM_DESTROY:
    PostQuitMessage(0);
    return 0;
  }
  return DefWindowProc(hwnd, message, wParam, lParam);
}

void CalculateStarPosition(POINT *stars, size_t nCount, size_t r, size_t angle, POINT BigStar)
{
    
    
  for (size_t i = 0; i < nCount; i++)

  {
    
    
    stars[i].x = BigStar.x + (LONG)(r * cos((angle + i * 72) * PI / 180));
    stars[i].y = BigStar.y - (LONG)(r * sin((angle + i * 72) * PI / 180));
  }
}

6. Ideas for drawing the five-star red flag

The position and drawing method of the five stars are as follows:

(1) To facilitate the determination of the positions of the five stars, first divide the flag face into four equal rectangles, divide the upper left rectangle into ten equal divisions up and down, and divide the left and right sides into fifteen equal divisions.

(2) The center point of the big five-pointed star is at the top five, five bottom five, left five and right ten of the rectangle. The drawing method is: take this point as the center and divide the radius into thirds to form a circle. On this circumference, five equidistant points are determined, one of which must be located directly above the circle. Then connect the two points that are apart from each other among the five points, so that each is in a straight line. The outline formed by these five straight lines is the required large five-pointed star. One of the five-pointed star pointed forward

(3) The center points of the four small five-pointed stars, the first point is at the position of two, eight, left, ten and right of the rectangle; the second point is at four, six, left, twelve and right; the third point is The fourth point is at the upper nine, lower three, left ten and right five. The drawing method is as follows: take the above four points as the center of the circle, divide each into a radius, and make four circles respectively.

Five equidistant points are determined on each circle, and one point must be located on the connecting lines between the center point of the big five-pointed star and the centers of the above four circles. Then use the same method to form the large pentagram to form the small pentagram. Each of these four small five-pointed stars has a point facing the central point of the large five-pointed star.

   // 把左上角矩形宽分为15份,高分为10份
  size_t flagWidth = 450 / 15;
  size_t flagHeight = 300 / 15;
  // 定位 大五角星圆心
  POINT BigStar = {
    
    (LONG)flagWidth * 5, (LONG)flagHeight * 5};
  size_t r = flagHeight * 3;

  // 第1个点90度
  POINT star1;
  star1.x = BigStar.x + (r * cos(90 * PI / 180));
  star1.y = BigStar.y - (r * sin(90 * PI / 180));
  // 第2个点162度
  POINT star2;
  star2.x = BigStar.x + (r * cos(162 * PI / 180));
  star2.y = BigStar.y - (r * sin(162 * PI / 180));
  // 第3个点234度
  POINT star3;
  star3.x = BigStar.x + (r * cos(234 * PI / 180));
  star3.y = BigStar.y - (r * sin(234 * PI / 180));
  // 第4个点306度
  POINT star4;
  star4.x = BigStar.x + (r * cos(306 * PI / 180));
  star4.y = BigStar.y - (r * sin(306 * PI / 180));
  // 第5个点378度
  POINT star5;
  star5.x = BigStar.x + (r * cos(378 * PI / 180));
  star5.y = BigStar.y - (r * sin(378 * PI / 180));

  POINT stars[5] = {
    
    star1, star3, star5, star2, star4};
  • Summary method
void CalculateStarPosition(POINT *stars, size_t nCount, size_t r, size_t angle, POINT BigStar)
{
    
    
  #define PI 3.1415926
  for (size_t i = 0; i < nCount; i++)

  {
    
    
    stars[i].x = BigStar.x + (LONG)(r * cos((angle + i * 72) * PI / 180));
    stars[i].y = BigStar.y - (LONG)(r * sin((angle + i * 72) * PI / 180));
  }
}

7. I don’t know if this is a bug

Obviously I set the color of the brush to yellow, but it doesn’t take effect, and it turns white directly. I don’t know how to solve this problem


enjoy it ~

Guess you like

Origin blog.csdn.net/a924282761/article/details/127575877