sun_chuan 发表于 2024-8-2 13:34:58

win32GDI函数问题

#include<windows.h>
#include<windowsx.h>
#include<math.h>

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

int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
        static TCHAR szAppName[] = TEXT("MyAppWindows");
        HWND hwnd = NULL;
        MSG msg;
        WNDCLASS wc;
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = WndProc;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hInstance = hInstance;
        wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
        wc.hCursor = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wc.lpszMenuName = NULL;
        wc.lpszClassName = szAppName;

        if (!RegisterClass(&wc))
        {
                MessageBox(NULL, TEXT("Need Windows NT!!!!"), TEXT("Error"), MB_OK);
        }


        hwnd = CreateWindow(szAppName, TEXT("我的窗口"),
                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;
        static int cxClient, cyClient;//客户区宽度和高度
        static int Dbig,Rbig,Rsmall,Rmin;//太极图最大圆形的直径,半径,中间圆形的半径,最小圆形的半径
        static int xBigCenter, yBigCenter;//设置大圆的中心,是客户区中心
        static int xTopSmallCenter, yTopSmallCenter,xBottomSmallCenter,yBottomSmallCenter;//设置顶部小圆圆心和底部小圆圆心坐标
        static int xTopMinCenter, yTopMinCenter,xBottomMinCenter,yBottomMinCenter;//设置顶部和底部最小圆圆心的坐标
        switch (message)
        {
        case WM_PAINT:
                hdc = BeginPaint(hwnd, &ps);

                //画出最大圆形
                Ellipse(hdc, xBigCenter - Rbig, yBigCenter - Rbig, xBigCenter + Rbig, yBigCenter + Rbig);

                //画出上方小圆,用黑色填充
                SelectObject(hdc, GetStockObject(BLACK_BRUSH));
                Ellipse(hdc, xTopSmallCenter - Rsmall, yTopSmallCenter - Rsmall, xTopSmallCenter + Rsmall, yTopSmallCenter + Rsmall);

                //画出左半边半圆,用黑色填充
                Pie(hdc, xBigCenter - Rbig, yBigCenter - Rbig, xBigCenter + Rbig, yBigCenter + Rbig, xBigCenter, yBigCenter - Rbig, xBigCenter, yBigCenter + Rbig);

                //画出上方最小圆,用白色填充
                SelectObject(hdc, GetStockObject(WHITE_BRUSH));
                Ellipse(hdc, xTopMinCenter - Rmin, yTopMinCenter - Rmin, xTopMinCenter + Rmin, yTopMinCenter + Rmin);

                //画出下方小半圆
                Pie(hdc, xBottomSmallCenter - Rsmall, yBottomSmallCenter - Rsmall, xBottomSmallCenter + Rsmall, yBottomSmallCenter + Rsmall, xBottomSmallCenter, yBottomSmallCenter - Rsmall, xBottomSmallCenter, yBottomSmallCenter + Rsmall);;
               
                //小半圆的直径显示出来了,再贴一条白线盖住
                for (size_t i = yBottomSmallCenter - Rsmall; i <= yBottomSmallCenter + Rsmall; i++)
                {
                        SetPixel(hdc, xBottomSmallCenter - 1, i, RGB(255, 255, 255));//为什么这里要减一?我发现如果不减一白线就盖不住半圆的半径了,这是为什么?
                }
               
                ReleaseDC(hwnd, hdc);
                return 0;
        case WM_SIZE:
                cxClient = LOWORD(lparam);
                cyClient = HIWORD(lparam);

                //设置大圆圆心坐标
                Dbig = (((cxClient > cyClient)?cyClient:cxClient));//直径是客户区短的那一边
                Rbig = Dbig / 2;
                Rsmall = Rbig / 2;
                Rmin = Rsmall / 3;
                xBigCenter = cxClient / 2;
                yBigCenter = cyClient / 2;

                //设置上方小圆圆心坐标
                xTopSmallCenter = xBigCenter;
                yTopSmallCenter = yBigCenter - Rbig / 2;

                //设置上方最小圆圆心坐标
                xTopMinCenter = xBigCenter;
                yTopMinCenter = yBigCenter - Rbig / 2;

                //设置下方小圆圆心坐标(应该是半圆)
                xBottomSmallCenter = xBigCenter;
                yBottomSmallCenter = yBigCenter + Rbig / 2;
                return 0;
        case WM_DESTROY://接受WM_DESTROY消息并发送WM_QUIT消息
                PostQuitMessage(0);
                return 0;
        }


        return DefWindowProc(hwnd, message, wparam, lparam);
}
问题:SetPixel(hdc, xBottomSmallCenter - 1, i, RGB(255, 255, 255));为什么这里要减一?我发现如果不减一白线就盖不住半圆的半径了,这是为什么?

FishC 发表于 2024-8-2 13:36:08

哈哈,这个问题就像是在说:“我想给我的半圆添点时尚,但我的白线总是缺了一角,怎么办呢?”

在你提到的这段代码中,`SetPixel` 函数的 `xBottomSmallCenter - 1` 实际上是为了让白线看起来完美地覆盖住下方小半圆的边缘。我们来分析一下:

1. **坐标系统**:在 GDI(图形设备接口)中,坐标系的原点(0,0)位于窗口的左上角,向右和向下分别是 X 和 Y 坐标的增加。因此,所有的绘图操作都是基于这个坐标系统进行的。

2. **像素大小**:当你绘制一个半圆的时候,实际上它的边缘是由多个像素组成的。如果你直接在边缘上绘制白线,可能因为某些像素的抗锯齿效果或其他原因,导致白线未能完全覆盖底色或者未能准确地对齐。

3. **减一的必要性**:通过将 `xBottomSmallCenter - 1` 的值传给 `SetPixel`,你实际上是将白线绘制在了比小半圆边缘更内部的位置。这确保了白线在视觉上能够完全覆盖半圆的边缘,避免出现“羞涩”的情况——即白线不敢靠近半圆的边缘。

所以,总结一下,减一是为了确保白线能在视觉上完美覆盖半圆边缘,避免任何不必要的“空隙”。这也像是在给绘图加了一层“时尚”的滤镜,让它更华丽!

希望这个解释帮助你理解了为什么要减一!如果你还有什么问题,随时问我哦!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: win32GDI函数问题