IT_Programming/MFC · API

[API] 더블 버퍼링 스크롤바 테스트!

JJun ™ 2009. 8. 4. 10:50

==================================================================================================

 

[실행화면]

 

- 초기화면

 

- X축 이동

 

- Y축 이동

 

:  더블 버퍼링을 활용해서 스크롤을 이동시켜 그림을 이동시켰을때 생기는 화면의 깜빡임을 제거했다.

 

==================================================================================================

 

[소스코드]

 

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

 

#define BALL_SIZE 10

 

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

 

BOOL WinMain_OnCreate(HWND, LPCREATESTRUCT);
void WinMain_OnPaint(HWND);
void WinMain_OnHScroll(HWND, HWND, UINT, int);
void WinMain_OnVScroll(HWND, HWND, UINT, int);
void WinMain_OnTimer(HWND, UINT);
void WinMain_OnDestroy(HWND);


//int getTrackPos(HWND, int);

 

int APIENTRY WinMain( HINSTANCE hInstance,

                                   HINSTANCE hPrevInstance,

                                   LPSTR lpCmdLine,

                                   int nShowCmd )
{
      MSG msg;
      HWND hwnd;
      WNDCLASS wndclass = {0};
 
      wndclass.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
      wndclass.hInstance  = hInstance;
      wndclass.lpfnWndProc = WndProc;
      wndclass.lpszClassName = TEXT("WinMain");
      wndclass.style   = CS_HREDRAW | CS_VREDRAW;
      RegisterClass(&wndclass);

 

      hwnd = CreateWindow (
                                          TEXT("WinMain"),
                                          TEXT("WinMain"),
                                          WS_OVERLAPPEDWINDOW,
                                          CW_USEDEFAULT,
                                          CW_USEDEFAULT,
                                          CW_USEDEFAULT,
                                          CW_USEDEFAULT,
                                          NULL,
                                          (HMENU) NULL,
                                          hInstance,
                                          NULL
                                    );
 
      ShowWindow(hwnd, nShowCmd);

     

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

 

      return (int)msg.wParam;
}

 

static int sx = 230, sy = 130;
HBITMAP hBit;
enum{ID_HSCROLL1, ID_VSCROLL1};

 

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
      switch(iMessage) // 메시지 크랙커
      {
            HANDLE_MSG(hwnd, WM_CREATE,  WinMain_OnCreate);
            HANDLE_MSG(hwnd, WM_PAINT,  WinMain_OnPaint);
            HANDLE_MSG(hwnd, WM_HSCROLL, WinMain_OnHScroll);
            HANDLE_MSG(hwnd, WM_VSCROLL, WinMain_OnVScroll);
            HANDLE_MSG(hwnd, WM_TIMER,  WinMain_OnTimer);
            HANDLE_MSG(hwnd, WM_DESTROY, WinMain_OnDestroy);
      }

     

      return (DefWindowProc(hwnd, iMessage, wParam, lParam));
}

 

BOOL WinMain_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
{
      MoveWindow(hwnd, 300, 200, 500, 300, TRUE);

 

      CreateWindow(   // 수평 스크롤 생성
                              TEXT("scrollbar"),
                              NULL,
                              WS_CHILD | WS_VISIBLE | SBS_HORZ,
                              20,
                              10,
                              430,
                              25,
                              hwnd,
                              (HMENU) ID_HSCROLL1,
                              GetModuleHandle(0),
                              NULL
                        );

 

      CreateWindow(   // 수직 스크롤 생성
                              TEXT("scrollbar"),
                              NULL,
                              WS_CHILD | WS_VISIBLE | SBS_VERT,
                              450,
                              35,
                              25,
                              220,
                              hwnd,
                              (HMENU) ID_VSCROLL1,
                              GetModuleHandle(0),
                              NULL
                        );

 

 SetScrollRange(GetDlgItem(hwnd, ID_HSCROLL1), SB_CTL, 45, 430, TRUE);
 SetScrollPos(GetDlgItem(hwnd, ID_HSCROLL1), SB_CTL, sx, TRUE);
 SetScrollRange(GetDlgItem(hwnd, ID_VSCROLL1), SB_CTL, 60, 230, TRUE);
 SetScrollPos(GetDlgItem(hwnd, ID_VSCROLL1), SB_CTL, sy, TRUE);
 
 SetTimer(hwnd, 1, 25, NULL); // Java의 더블 버퍼링 구현에서 Thread.Sleep(...)과 같은 역할

 

 return TRUE;
}

 

void WinMain_OnPaint(HWND hwnd)
{
      char  resultCheck[200];
      HDC   hdc, hMemDC;
      HBITMAP  OldBit;
      RECT  rect;
      PAINTSTRUCT ps;
 
      // 그려진 비트맵 개체를 메모리 DC로 받아서 화면에 출력!
      hdc    = BeginPaint(hwnd, &ps);
      hMemDC   = CreateCompatibleDC(hdc);    
      OldBit    = (HBITMAP)SelectObject(hMemDC, hBit);

      GetClientRect(hwnd, &rect);  // 작업영역 획득!

     

      // 화면DC와 메모리DC 영역 복사
      BitBlt(hdc, 0, 40, rect.right-50, rect.bottom, hMemDC, 0, 40, SRCCOPY);

      

      SelectObject(hMemDC, OldBit); 
      DeleteDC(hMemDC);       // 리소스 해제
      EndPaint(hwnd, &ps);      // 리소스 해제
      wsprintf(resultCheck, "%d, %d", sx, sy); // 좌표 세팅
      SetWindowText(hwnd, resultCheck);      // 윈도우 캡션에 좌표 출력
}

 

void WinMain_OnHScroll(HWND hwnd, HWND hwndCtl, UINT code, int pos)
{
      switch(code)
      {
            case SB_LINELEFT :
                  sx = max(45, sx-20);
                  break;

 

            case SB_LINERIGHT :
                  sx = min(430, sx+20);
                  break;
   
            case SB_PAGELEFT :
                  sx = max(45, sx-60);
                  break;

 

            case SB_PAGERIGHT :
                  sx = min(430, sx+60);
                  break;

 

            case SB_THUMBTRACK : 
                  sx = pos; // getTrackPos(hwnd, ID_HSCROLL1);
                  break;
      }

 

      SetScrollPos(hwndCtl, SB_CTL, sx, TRUE);
}

 

void WinMain_OnVScroll(HWND hwnd, HWND hwndCtl, UINT code, int pos)
{
      switch(code)
      {
            case SB_LINEUP :
                  sy = max(60, sy-20);
                  break;

 

            case SB_LINEDOWN :
                  sy = min(230, sy+20);
                  break;

 

            case SB_PAGEUP :
                  sy = max(60, sy-60);
                  break;

 

            case SB_PAGEDOWN :
                  sy = min(230, sy+60);
                  break;

 

            case SB_THUMBTRACK :
                  sy = pos; //getTrackPos(hwnd, ID_VSCROLL1);
                  break;
      }

 

      SetScrollPos(hwndCtl, SB_CTL, sy, TRUE);
}

 

void WinMain_OnTimer(HWND hwnd, UINT id)
{
      HDC  hdc, MemDC;
      RECT rect;
      HBITMAP OldbitMap;
      HBRUSH hBrush, OldBrush;

     

      GetClientRect(hwnd, &rect);
      hdc       = GetDC(hwnd);
      MemDC     = CreateCompatibleDC(hdc); // 화면 DC에 대응하는 메모리 DC 생성
 
      if (hBit == NULL) // 전역변수 hBit가 생성이 되어 있지 않다면.. 생성
            hBit = CreateCompatibleBitmap(hdc, rect.right, rect.bottom);

 

      OldbitMap = (HBITMAP)SelectObject(MemDC, hBit); 
      FillRect(MemDC, &rect, GetSysColorBrush(COLOR_3DFACE)); // 화면 배경

 

      hBrush    = CreateSolidBrush(RGB(0, 0, 255));   // 공 색깔에 해당하는 브러쉬 개체 생성
      OldBrush  = (HBRUSH)SelectObject(MemDC, hBrush);  // 이전의 브러쉬 저장
      Ellipse(MemDC, sx-BALL_SIZE, sy-BALL_SIZE, sx+BALL_SIZE, sy+BALL_SIZE);
 
      // 이전의 브러쉬로 돌려 놓고 사용했던 브러쉬 자원 해제
      DeleteObject(SelectObject(MemDC, OldBrush)); 

      SelectObject(MemDC, OldbitMap); 
      DeleteDC(MemDC);
      ReleaseDC(hwnd, hdc);
 
      InvalidateRect(hwnd, NULL, FALSE); // WM_PAINT 메시지를 발생시킴
}

 

void WinMain_OnDestroy(HWND hwnd)
{
      PostQuitMessage(0);
}

 

/*
int getTrackPos(HWND hwnd, int id)
{
      SCROLLINFO si;
      si.cbSize = sizeof(SCROLLINFO);
      si.fMask = SIF_TRACKPOS;
      GetScrollInfo(GetDlgItem(hwnd, id), SB_CTL, &si);
 
      return si.nTrackPos;
}
*/

 

==================================================================================================