본문 바로가기

Windows/Windows API

스크롤바 란에 정보 넣기(scrollbar, MoveWindow, PrintPosition)

#include <windows.h>

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
HWND g_hWndMain;
LPSTR lpszClass="ScrWnd2";

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
         ,LPSTR lpszCmdParam,int nCmdShow)
{
    HWND hWnd;
    MSG Message;
    WNDCLASS WndClass;
    g_hInst=hInstance;
    
    if(!hPrevInstance) {
        WndClass.cbClsExtra=0;
        WndClass.cbWndExtra=0;
        WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
        WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
        WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
        WndClass.hInstance=hInstance;
        WndClass.lpfnWndProc=(WNDPROC)WndProc;
        WndClass.lpszClassName=lpszClass;
        WndClass.lpszMenuName=NULL;
        WndClass.style=CS_HREDRAW | CS_VREDRAW;
        RegisterClass(&WndClass);
    }
    hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
         CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
         NULL,(HMENU)NULL,hInstance,NULL);
    g_hWndMain=hWnd;
    ShowWindow(hWnd,nCmdShow);
    
    while(GetMessage(&Message,0,0,0)) {
        TranslateMessage(&Message);
        DispatchMessage(&Message);
    }
    return Message.wParam;
}

// 전역 변수 및 매크로 상수
#define ID_HORZSCROLL 100
#define ID_VERTSCROLL 101
HWND hHorzScroll;            // 수평 스크롤 바 컨트롤
HWND hVertScroll;            // 수직 스크롤 바 컨트롤
int yPos,xPos;                // 현재 위치
int yMax,xMax;                // 최대 크기
int SW;                        // 스크롤 바의 높이

// 수평 스크롤 바 왼쪽에 현재 위치를 출력하는 함수
// 스크롤 바 영역은 무효화 영역에서 제외되기 때문에 WM_PAINT에서
// 현재 위치를 출력할 수 없어서 별도의 함수로 분리하였다.
void PrintPosition()
{
    HDC hdc;
    char str[128];
    RECT crt;
    hdc=GetDC(g_hWndMain);

    GetClientRect(g_hWndMain,&crt);
    SelectObject(hdc,GetStockObject(BLACK_BRUSH));
    Rectangle(hdc,0,crt.bottom-SW,200,crt.bottom);
    SetTextColor(hdc,RGB(255,255,255));
    SetBkColor(hdc,RGB(0,0,0));
    wsprintf(str,"현재 위치 => X:%d, Y:%d",xPos,yPos);
    TextOut(hdc,5,crt.bottom-SW,str,strlen(str));
    ReleaseDC(g_hWndMain,hdc);
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
    int i;
    char str[128];
    HDC hdc;
    PAINTSTRUCT ps;
    int xInc, yInc;
    SCROLLINFO si;
    RECT crt,rt;
    switch(iMessage) {
    case WM_CREATE:
        // 두 개의 스크롤 바 컨트롤을 만든다.
        hHorzScroll=CreateWindow("scrollbar",NULL,WS_CHILD | WS_VISIBLE | SBS_HORZ,
            0,0,0,0,hWnd,(HMENU)ID_HORZSCROLL,g_hInst,NULL);
        hVertScroll=CreateWindow("scrollbar",NULL,WS_CHILD | WS_VISIBLE | SBS_VERT,
            0,0,0,0,hWnd,(HMENU)ID_VERTSCROLL,g_hInst,NULL);
        xPos=0;
        yPos=0;
        xMax=1024;
        yMax=768;
        // 스크롤 바의 높이를 구해 놓는다.
        SW=GetSystemMetrics(SM_CYHSCROLL);
        return 0;
    case WM_SIZE:
        si.cbSize=sizeof(SCROLLINFO);
        si.fMask=SIF_ALL | SIF_DISABLENOSCROLL;
        si.nMin=0;
        si.nMax=768;
        si.nPage=HIWORD(lParam)-SW;
        si.nPos=yPos;
        SetScrollInfo(hVertScroll, SB_CTL, &si, TRUE);

        si.nMax=1024;
        si.nPage=LOWORD(lParam)-SW;
        si.nPos=xPos;
        SetScrollInfo(hHorzScroll, SB_CTL, &si, TRUE);

        // 스크롤 바가 별도의 컨트롤이므로 메인 윈도우의 크기가 변경
        // 되면 스크롤 바의 위치도 따라서 변경되어야 한다.
        MoveWindow(hHorzScroll,200,HIWORD(lParam)-SW,
            LOWORD(lParam)-SW-200,SW,TRUE);
        MoveWindow(hVertScroll,LOWORD(lParam)-SW,0,SW,
            HIWORD(lParam)-SW,TRUE);
        return 0;
    case WM_HSCROLL:
        xInc=0;
        switch (LOWORD(wParam)) {
        case SB_LINEUP:
            xInc=-1;
            break;
        case SB_LINEDOWN:
            xInc=1;
            break;
        case SB_PAGEUP:
            xInc=-20;
            break;
        case SB_PAGEDOWN:
            xInc=20;
            break;
        case SB_THUMBTRACK:
            xInc=HIWORD(wParam)-xPos;
            break;
        default:
            break;
        }
        if (xPos+xInc < 0)
            xInc=-xPos;
        if (xPos+xInc > xMax)
            xInc=xMax-xPos;
        xPos=xPos+xInc;
        // 스크롤 바 영역을 제외한 부분만 스크롤시킨다.
        GetClientRect(hWnd,&crt);
        SetRect(&rt,0,0,crt.right-SW,crt.bottom-SW);
        ScrollWindow(hWnd, -xInc, 0, &rt, &rt);
        SetScrollPos(hHorzScroll, SB_CTL, xPos, TRUE);
        // 스크롤한 후 현재 위치를 출력한다.
        PrintPosition();
        return 0;
    case WM_VSCROLL:
        yInc=0;
        switch (LOWORD(wParam)) {
        case SB_LINEUP:
            yInc=-1;
            break;
        case SB_LINEDOWN:
            yInc=1;
            break;
        case SB_PAGEUP:
            yInc=-20;
            break;
        case SB_PAGEDOWN:
            yInc=20;
            break;
        case SB_THUMBTRACK:
            yInc=HIWORD(wParam)-yPos;
            break;
        default:
            break;
        }
        if (yPos+yInc < 0)
            yInc=-yPos;
        if (yPos+yInc > yMax)
            yInc=yMax-yPos;
        yPos=yPos+yInc;
        // 스크롤 바 영역을 제외한 부분만 스크롤시킨다.
        GetClientRect(hWnd,&crt);
        SetRect(&rt,0,0,crt.right-SW,crt.bottom-SW);
        ScrollWindow(hWnd, 0, -yInc, &rt, &rt);
        SetScrollPos(hVertScroll, SB_CTL, yPos, TRUE);
        // 스크롤한 후 현재 위치를 출력한다.
        PrintPosition();
        return 0;
    case WM_PAINT:
        hdc=BeginPaint(hWnd, &ps);
        for (i=0;i<1024;i+=50) {
            wsprintf(str,"%d",i);
            TextOut(hdc,i-xPos,0-yPos,str,strlen(str));
            TextOut(hdc,i-xPos,750-yPos,str,strlen(str));
        }
        for (i=0;i<768;i+=50) {
            wsprintf(str,"%d",i);
            TextOut(hdc,0-xPos,i-yPos,str,strlen(str));
            TextOut(hdc,1000-xPos,i-yPos,str,strlen(str));
        }
        MoveToEx(hdc,500-xPos,100-yPos,NULL);
        LineTo(hdc,500-xPos,668-yPos);
        MoveToEx(hdc,100-xPos,380-yPos,NULL);
        LineTo(hdc,924-xPos,380-yPos);
        PrintPosition();
        EndPaint(hWnd, &ps);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}