5. [pywin32] LineAndCurve 관련 함수 - 1

pywin32/win32gui|2021. 12. 10. 00:40

1. PyGdiHANDLE = CreatePen(PenStyle, Width , Color )

선 그리기에 사용할 Pen 스타일을 지정해서 Pen 핸들값을 만드는 함수입니다.

 

인자로는 PenStyle : int, Width : int, Color : int 가 있습니다.

 

PenSytle: Pen의 스타일을 지정합니다.

 * 참조: https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createpen

 

Width: Pen의 굵기를 지정합니다. 0으로 설정 시 1픽셀의 굵기를 갖습니다.

 

Color: Pen의 색을 지정합니다. win32api.RGB() 함수를 사용합니다.

 

리턴값은 Pen 핸들값입니다.

 

 

2. PyHANDLE = ExtCreatePen(PenStyle, Width , lb , Style )

CreatePen()함수처럼 Pen 스타일을 만드는 함수입니다. CreatePen()함수보다 여러 설정값을 가질 수 있습니다.

 

인자로는 PenStyle : int, Width : intlb : PyLOGBRUSH, Style=None : (int, ...) 가 있습니다.

 

PenStyle: Pen의 스타일을 지정합니다. 반드시 win32con.PS_GEOMETRIC, win32con.PS_COSMETIC 둘 중 하나를 포함해야 합니다. 그런데 두 스타일의 차이가 아직 이해가 안가더군요...

 * 참조: https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-extcreatepen

 

Width: Pen의 굵기를 지정합니다. PenStyle에 win32con.PS_COSMETIC 이 있으면, 반드시 1이여햐 한다고 합니다.

 

lb: PyLOGBRUSH 라는 사전형 값을 가집니다. Pen 에 지정할 Brush 값을 나타내는 듯 합니다. PenStyle에 win32con.PS_COSMETIC 이 있으면, 'Style'이 반드시 win32con.BS_SOLID 여야 합니다.

 * PyLOGBRUSH (사전형)

  - 'Style': Brush 스타일 지정

  - 'Color': win32api.RGB() 함수로 지정하는 색

  - 'Hatch': Hatch 스타일 지정(Hatch는 무늬를 뜻하는 듯 합니다.), BS_SOLID와 BS_HOLLOW에는 필요없는 값이라고 합니다.

   * 참조: https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-logbrush

 

Style: PS_USERSTYLE 일 때만 사용하는 값으로 사용자 지정 스타일을 줄 떄 사용되는 값인 듯 합니다.

 

리턴값은 Pen 핸들값입니다.

 

 

3. HGDIOBJ = SelectObject(hdc, object )

위의 CreatePen()함수처럼 GDI 핸들을 만든 후 SelectObject()함수를 사용해야 프로그램에 적용할 수 있습니다.

 

인자로는 hdc : int, object : int 가 있습니다.

 

hdc: device context 핸들 값입니다.

 

object: 적용할 GDI 핸들값입니다.

 

리턴값은 새로운 GDI 객체를 적용하기 전 사용하고 있던 GDI 객체입니다. 나중에 GDI 객체를 다시 되돌리고 싶을 때 사용합니다.

 

 

4. DeleteObject(handle)

사용하지 않는 GDI 핸들을 삭제하는 함수입니다.

 

인자로는 handle : PyGdiHANDLE 가 있습니다.

 

handle: 삭제할 GDI 핸들 값입니다.

 

 

5. int = SetArcDirection(hdc, ArcDirection )

도형을 그릴 때 그리는 방향을 지정하는 함수입니다. 기본값은 반시계 방향입니다.

 

인자로는 hdc : PyHANDLE, ArcDirection : int 가 있습니다.

 

hdc: device context 핸들값

 

ArcDirection: 그리기 방향. 아래의 값 둘 중 하나를 설정가능합니다.

 - win32con.AD_COUNTERCLOCKWISE: 반시계 방향

 - win32con.AD_CLOCKWISE: 시계 방향

 

리턴값으로는 기존의 방향 값을 리턴합니다.

 

 

6. int = GetArcDirection(hdc)

현재 그리기 방향이 무엇인지 반환하는 함수입니다.

 

인자로는 hdc : PyHANDLE가 있습니다.

 

hdc: device context 핸들값

 

리턴값으로는 현재 설정된 그리기 방향 값을 리턴합니다.

 

 

7. (int, int) = MoveToEx(hdc, X , Y )

현재의 위치를 이동시켜줍니다. 선이나 도형을 그릴 때 어디에서 부터 그릴 것인지를 정할 수 있습니다. (보통 왼쪽상단에서 시작합니다.)

 

인자로는 hdc : PyHANDLE, X : int, Y : int 가 있습니다.

 

hdc: device context 핸들값

 

X: 이동할 x 좌표 (왼쪽상단 위 기준, 오른쪽방향)

 

Y: 이동할 y 좌표 (왼쪽상단 위 기준, 아래방향)

 

리턴값은 기존의 x,y 좌표입니다.

 

 

8. LineTo(hdc, XEnd, YEnd)

현재위치에서 지정된 위치까지 선을 그리는 함수입니다. 끝에 To 가 들어간 함수이므로, MoveToEx()함수처럼 위치를 이동시켜주는 역할도 합니다. 현재위치에서 지정된 위치까지 선을 그리고, 현재위치가 지정된 위치로 이동하게 됩니다. 그래서 LinTo()함수를 계속 호출하면 선이 계속 이어지게 됩니다.

 

인자로는 hdc : PyHANDLE, XEnd : int, YEnd : int 가 있습니다.

 

hdc: device context 핸들값

 

X: 지정할 위치의 x 좌표 (왼쪽상단 위 기준, 오른쪽방향)

 

Y: 지정할 위치의 y 좌표 (왼쪽상단 위 기준, 아래방향)

 

 

이 외에도 추가적인 함수에 대한 설명은 2부에서 하고, 일단 예제를 올려두겠습니다. 번호 별로 주석처리 및 해제를 해보시면서 실행시켜보시면 됩니다.

 

 

from typing import cast
import win32gui
import win32api
import win32con

# WM_CREATE가 안생겨서 만든 WM_CREATE 대용 메시지
UM_CREATE = win32con.WM_USER + 1


class WindowProcFunc:
    def __init__(self):
        pass

    def OnCreate(self, hwnd, iMsg, wParam, lParam):
        pass

        
    def OnDestroy(self, hwnd, iMsg, wParam, lParam):
        win32gui.PostQuitMessage(0)


    def OnPaint(self, hwnd, iMsg, wParam, lParam):
        hdc, ps = win32gui.BeginPaint(hwnd)

        #hPen = win32gui.CreatePen(win32con.PS_DOT, 1, win32api.RGB(255, 0, 0))
        lb = {'Style' : win32con.BS_SOLID, 'Color':win32api.RGB(255, 0, 0), 'Hatch':None} 
        hPen = win32gui.ExtCreatePen(win32con.PS_COSMETIC | win32con.PS_DOT, 1, lb, None)
        oldPen = win32gui.SelectObject(hdc, hPen)
        

        win32gui.SetArcDirection(hdc, win32con.AD_CLOCKWISE)

        # 1번
        #win32gui.Arc(hdc, 300, 10, 400, 100, 400, 10, 400, 100)
        
        # 2번 
        #win32gui.MoveToEx(hdc, 350, 150)
        #win32gui.ArcTo(hdc, 300, 10, 400, 100, 400, 10, 400, 100)

        # 3번
        win32gui.MoveToEx(hdc, 300, 100)
        win32gui.AngleArc(hdc, 300, 100, 100, 30, 60)

        # 4번
        prePos = win32gui.MoveToEx(hdc, 10, 10)
        win32gui.LineTo(hdc, 50, 50)

        # 5번
        polygonPos=((10, 75), (125, 30), (250, 75), (175, 150), (75, 150))
        win32gui.Polyline(hdc, polygonPos)
        
        #6번
        #prePos = win32gui.MoveToEx(hdc, 400, 400)
        #win32gui.PolylineTo(hdc,polygonPos)
        
        # 7번
        bezierPos=((55, 215), (75, 100), (200, 300), (275, 75))
        #win32gui.PolyBezier(hdc, bezierPos)

        #8번
        bezierToPos=((75, 100), (200, 300), (275, 75))
        prePos = win32gui.MoveToEx(hdc, 55, 215)
        win32gui.PolyBezierTo(hdc, bezierToPos)
        

        win32gui.SelectObject(hdc, oldPen)
        win32gui.DeleteObject(hPen)

        arcDirect = win32gui.GetArcDirection(hdc)
        print(f"Arc Direct : {'시계방향' if win32con.AD_CLOCKWISE==arcDirect else '반시계방향'}")

        win32gui.EndPaint(hwnd, ps)


    def OnClose(self, hwnd, iMsg, wParam, lParam):
        win32gui.DestroyWindow(hwnd)


wndProcFunc = WindowProcFunc()

wndProc={
    UM_CREATE:wndProcFunc.OnCreate,
    win32con.WM_DESTROY: wndProcFunc.OnDestroy,
    win32con.WM_PAINT: wndProcFunc.OnPaint,
    win32con.WM_CLOSE: wndProcFunc.OnClose,
}

def winMain():
    hInstance = win32api.GetModuleHandle()


    className = 'SimpleWin32'

    wndClass                = win32gui.WNDCLASS()
    wndClass.style          = win32con.CS_HREDRAW | win32con.CS_VREDRAW
    wndClass.lpfnWndProc    = wndProc
    wndClass.hInstance      = hInstance
    wndClass.hIcon          = win32gui.LoadIcon(0, win32con.IDI_APPLICATION)
    wndClass.hCursor        = win32gui.LoadCursor(0, win32con.IDC_ARROW)
    wndClass.hbrBackground  = win32gui.GetStockObject(win32con.WHITE_BRUSH)
    wndClass.lpszClassName  = className

    wndClassAtom = win32gui.RegisterClass(wndClass)

    hwnd = win32gui.CreateWindow(
        wndClassAtom,
        "title test",
        win32con.WS_OVERLAPPEDWINDOW | win32con.WS_VSCROLL | win32con.WS_HSCROLL,
        win32con.CW_USEDEFAULT,
        win32con.CW_USEDEFAULT,
        win32con.CW_USEDEFAULT,
        win32con.CW_USEDEFAULT,
        0,
        0,
        hInstance,
        None)

    win32gui.SendMessage(hwnd, UM_CREATE, 0, 0)

    win32gui.ShowWindow(hwnd, win32con.SW_SHOWNORMAL)
    win32gui.UpdateWindow(hwnd)

    win32gui.PumpMessages()
    return 0


if __name__ == "__main__":
    x = winMain()

 

 

 

 

반응형

댓글()