1 / 50

자식 윈도우 제어

8. 자식 윈도우 제어. 1. 자식 윈도우 제어. 부모 윈도우의 handle 을 알아내기 hwndParent = GetParent(hwnd); 부모 윈도우에 메시지 보내기 SendMessage(hwndParent,message,wParam,lParam); 자식 컨트롤 만들기 CreateWindow() 로 자식 윈도우를 만든다 . MoveWindow() 호출로 자식 윈도우의 위치와 크기를 조절한다 .

ivrit
Télécharger la présentation

자식 윈도우 제어

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 8. 자식 윈도우 제어

  2. 1. 자식 윈도우 제어 • 부모 윈도우의 handle을 알아내기 • hwndParent = GetParent(hwnd); • 부모 윈도우에 메시지 보내기 • SendMessage(hwndParent,message,wParam,lParam); • 자식 컨트롤 만들기 • CreateWindow()로 자식 윈도우를 만든다. • MoveWindow()호출로 자식 윈도우의 위치와 크기를 조절한다. • 미리 정의된 컨트롤(단추,체크 상자,편집 상자,목록 상자…) 중 하나를 만들 때는 자식 윈도우의 클래스가 이미 윈도우에 등록되어 있기 때문에 윈도우 클래스를 등록할 필요가 없다. • 각각의 단추를 클릭하면자식 윈도우 컨트롤은 자신의 부모 윈도우에게 WM_COMMAND메시지를 보낸다. • LOWORD(wParam) : 자식윈도우 ID • HIWORD(wParam) : 알림코드 • lParam : 자식윈도우의 핸들 • BS_OWNERDRAW • 사용자가 책임지고 버튼을 그려야 한다. • 버튼이 그려져야 할 경우에 부모에게 WM_DRAWITEM메시지를 보낸다. • lParam : DRAWITEMSTRUCT구조체의 포인터가 들어 있다.

  3. /*---------------------------------------- BTNLOOK.C -- Button Look Program (c) Charles Petzold, 1998 ----------------------------------------*/ #include <windows.h> struct { int iStyle ; TCHAR * szText ; } button[] = { BS_PUSHBUTTON, TEXT ("PUSHBUTTON"), BS_DEFPUSHBUTTON, TEXT ("DEFPUSHBUTTON"), BS_CHECKBOX, TEXT ("CHECKBOX"), BS_AUTOCHECKBOX, TEXT ("AUTOCHECKBOX"), BS_RADIOBUTTON, TEXT ("RADIOBUTTON"), BS_3STATE, TEXT ("3STATE"), BS_AUTO3STATE, TEXT ("AUTO3STATE"), BS_GROUPBOX, TEXT ("GROUPBOX"), BS_AUTORADIOBUTTON, TEXT ("AUTORADIO"), BS_OWNERDRAW, TEXT ("OWNERDRAW") }; #define NUM (sizeof button / sizeof button[0]) LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("BtnLook") ; 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 ("This program requires Windows NT!"),szAppName, MB_ICONERROR) ; return 0 ; }

  4. hwnd = CreateWindow (szAppName, TEXT ("Button Look"),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) { static HWND hwndButton[NUM] ; static RECT rect ; static TCHAR szTop[] = TEXT ("message wParam lParam"), szUnd[] = TEXT ("_______ ______ ______"), szFormat[] = TEXT ("%-16s%04X-%04X %04X-%04X"), szBuffer[50] ; static int cxChar, cyChar ; HDC hdc ; PAINTSTRUCT ps ; int i ; switch (message) { case WM_CREATE : cxChar = LOWORD (GetDialogBaseUnits ()) ; cyChar = HIWORD (GetDialogBaseUnits ()) ; for (i = 0 ; i < NUM ; i++) hwndButton[i] = CreateWindow ( TEXT("button"),button[i].szText, WS_CHILD | WS_VISIBLE | button[i].iStyle,cxChar, cyChar * (1 + 2 * i), 20 * cxChar, 7 * cyChar / 4,hwnd, (HMENU) i,((LPCREATESTRUCT) lParam)->hInstance, NULL) ; return 0 ; case WM_SIZE : rect.left = 24 * cxChar ; rect.top = 2 * cyChar ; rect.right = LOWORD (lParam) ; rect.bottom = HIWORD (lParam) ; return 0 ;

  5. case WM_PAINT : InvalidateRect (hwnd, &rect, TRUE) ; hdc = BeginPaint (hwnd, &ps) ; SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ; SetBkMode (hdc, TRANSPARENT) ; TextOut (hdc, 24 * cxChar, cyChar, szTop, lstrlen (szTop)) ; TextOut (hdc, 24 * cxChar, cyChar, szUnd, lstrlen (szUnd)) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DRAWITEM : case WM_COMMAND : ScrollWindow (hwnd, 0, -cyChar, &rect, &rect) ; hdc = GetDC (hwnd) ; SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ; TextOut (hdc, 24 * cxChar, cyChar * (rect.bottom / cyChar - 1), szBuffer, wsprintf (szBuffer, szFormat, message == WM_DRAWITEM ? TEXT ("WM_DRAWITEM") : TEXT ("WM_COMMAND"), HIWORD (wParam), LOWORD (wParam), HIWORD (lParam), LOWORD (lParam))) ; ReleaseDC (hwnd, hdc) ; ValidateRect (hwnd, &rect) ; break ; case WM_DESTROY : PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; }

  6. 1. 자식 윈도우 제어 • 단추 클래스 • class name : “button” • WindowText : button[I].szText • Window Style : WS_CHILD|WS_VISIBLE|button[I] • x Position : cxChar • y Position : cyChar * (1 + 2 * I) • Width : 20 * xChar • Height : 7 * yChar / 4 • Parent Window : hwnd • Child window ID : (HMENU) I • Instance handle : ((LPCREATSTRUCT) lParam) ->hInstance • Extra parameters : NULL • 인스턴스 핸들을 얻는 방법 3가지 • WM_CREATE시 : • lParam에 CREATESTRUCT형식의 구조체에 대한 포인터가 들어 있다. • 전역변수를 이용하는 방법 • hInst = hInstance; • GetWindowLong(hwnd,GWL_HINSTANCE)

  7. 2. 자식 윈도우가 부모 윈도우에 메시지 보내기 • 자식 윈도우 컨트롤은 자신의 부모 윈도우에게 WM_COMMAND메시지를 보낸다. • LOWORD(wParam) : 자식윈도우 ID • HIWORD(wParam) : 알림코드 • lParam : 자식윈도우의 핸들 • 단추 알림코드의 가능한 값들 • BN_CLICKED : 0 • BN_PAINT : 1 • BN_HILITE or BN_PUSHED : 2 • BN_UNHILITE or BN_UNPUSHED : 3 • BN_DISABLE : 4 • BN_DOUBLECLICKED or BN_DBLCLK : 5 • BN_SETFOCUS : 6 • BN_KILLFOCUS : 7 • 알림코드 6과 7은 단추 스타일이 BS_NOTIFY를 포함하는 경우에만 전달된다.

  8. 3. 부모 윈도우가 자식윈도우에게 보내는 메시지 • BM : Button Message • BM_GETCHECK • BM_SETCHECK • 체크박스와 라디오 단추의 체크표시를 설정하기 위해서 보낸다. • BM_GETSTATE • BM_SETSTATE • 한 윈도우를 마우스로 누르거나 Space Bar를 눌렀을 때의 상태를 의미한다. • BM_SETSTYLE • 단추가 만들어진 후 단추의 스타일을 변경할 수 있게 한다. • BM_CLICK • BM_GETIMAGE • BM_SETIMAGE • 자식 윈도우의 ID를 얻기 • Id = GetWindowLong(hwndChild,GWL_ID); • Id = GetDlgCtlID(hwndChild); • ID를 아는 상태에서 자식윈도우의 핸들 얻기 • hwndChild = GetDlgItem(hwndParent,ID);

  9. 4. 누르기 단추 • 마우스로 단추를 누르고 떼면 원래의 모양으로 되돌아오고 부모에게 WM_COMMAND메시지와 함께 알림코드로 BN_CLICKED를 보낸다. • 단추 윈도우에 BM_SETSTATE메시지를 보냄으로써 단추의 누른 상태를 지정할 수 있다. • SendMessage(hwndButton,BM_SETSTATE,1,0); • 다음의 호출로 단추는 정상으로 돌아 온다. • SendMessage(hwndButton,BM_SETSTATE,0,0); • 누르기 단추의 상태를 알려면 • SendMessage(hwndButton,BM_GETSTATE,0,0); • 단추가 눌려졌으면 TRUE를, 정상 상태이면 FALSE를 반환한다.

  10. 5. 체크 상자 • 체크 상자의 일반적인 두 가지 유형 • BS_CHECKBOX • 컨트롤에 BM_SETCHECK메시지를 전달한 후 체크 표시를 설정해야 한다. • wParam : 체크표시 1 , 제거 0 • BM_GETCHECK메시지를 전달하여 Check상태를 얻을 수 있다. • SendMessage((HWND)lParam,BM_SETCHECK, (WPARAM)!SendMessage((HWND)lParam, BM_GETCHECK,0,0),0); • BS_AUTOCHECKBOX • 자동으로 자신이 Check표시를 토글 한다. • iCheck =(int)SendMessage(hwndButton,BM_GETCHECK,0,0); • 체크되어 있으면 : TRUE • 체크되어 있지 않으면 : FALSE

  11. 6. 라디오 단추 • 라디오 단추에서 WM_COMMAND를 받을 때는 wParam이 1인 BM_SETCHECK메시지를 보내 체크를 표시한다. • SendMessage(hwndButton,BM_SETCHECK,1,0); • 같은 그룹에 있는 모든 라디오 단추에 wParam이 0인 BM_SETCHECK메시지를 전달하여 체크 설정을 취소한다. • SendMessage(hwndButton,BM_SETCHECK,0,0); • 단추 텍스트 변경하기 • SetWindowText를 호출하면 텍스트를 변경할 수 있다. • SetWindowText(hwnd,pszString); • iLength = GetWindowText(hwnd,pszBuffer,iMaxLength) • iMaxLength는 복사할 문자의 최대 개수를 지정 • iLength = GetWindowTextLength(hwnd);

  12. 7. 보이는 단추와 사용 가능한 단추 • 자식윈도우를 만들 때 WS_VISIBLE을 포함하지 않으면 ShowWindow를 호출할 때까지 자식 윈도우를 표시하지 않는다. • 윈도우를 보이게 한다. • ShowWindow(hwndChild,SW_SHOWNORMAL); • 윈도우를 숨긴다. • ShowWindow(hwndChild,SW_HIDE); • 자식윈도우가 보이는지 보이지 않는지를 알아낸다. • IsWindowVisible(hwndChild) • 자식윈도우를 사용 가능하게 하거나 불가능하게 한다. • EnableWindow(hwndChild,FALSE); • IsWindowEnabled(hwndChild);

  13. 8. 단추와 입력 포커스 case WM_KILLFOCUS: for ( i = 0; i < NUM; i++) { if (hwndChild[I] == (HWND)wParam) { SetFocus(hwnd); break; } } case WM_KILLFOCUS: if (hwnd == GetParetn((HWND)wParam) { SetFocus(hwnd); break; } • WM_KILLFOCUS시에 wParam 매개 변수는 입력 포커스를 받는 윈도우의 핸들이다.

  14. 8. WM_CTLCOLORBTN메시지 • 이 메시지는 자식 윈도우가 자신의 클라이언트 영역을 표시할 때 단추 컨트롤이 부모 윈도우에게 보내는 메시지이다. • wParam : 단추의 장치 컨텍스트에 대한 핸들 • lParam : 단추의 윈도우 핸들 • SetTextColor를 사용하여 텍스트 색상을 설정한다. • SetBkColor를 사용하여 텍스트 배경을 설정한다. • 자식 윈도우에 브러쉬 핸들을 반환한다.

  15. #include <windows.h> #define ID_SMALLER 1 #define ID_LARGER 2 #define BTN_WIDTH (8 * cxChar) #define BTN_HEIGHT (4 * cyChar) LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; HINSTANCE hInst ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("OwnDraw") ; MSG msg ; HWND hwnd ; WNDCLASS wndclass ; hInst = hInstance ; 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 = szAppName ; wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass)) { MessageBox (NULL, TEXT ("This program requires Windows NT!"),szAppName, MB_ICONERROR) ; return 0 ; } hwnd = CreateWindow (szAppName, TEXT ("Owner-Draw Button Demo"),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 ; }

  16. void Triangle (HDC hdc, POINT pt[]) { SelectObject (hdc, GetStockObject (BLACK_BRUSH)) ; Polygon (hdc, pt, 3) ; SelectObject (hdc, GetStockObject (WHITE_BRUSH)) ; } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hwndSmaller, hwndLarger ; static int cxClient, cyClient, cxChar, cyChar ; int cx, cy ; LPDRAWITEMSTRUCT pdis ; POINT pt[3] ; RECT rc ; switch (message) { case WM_CREATE : cxChar = LOWORD (GetDialogBaseUnits ()) ; cyChar = HIWORD (GetDialogBaseUnits ()) ; // Create the owner-draw pushbuttons hwndSmaller = CreateWindow (TEXT ("button"), TEXT (""), WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 0, 0, BTN_WIDTH, BTN_HEIGHT,hwnd, (HMENU) ID_SMALLER, hInst, NULL) ; hwndLarger = CreateWindow (TEXT ("button"), TEXT (""), WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, 0, 0, BTN_WIDTH, BTN_HEIGHT, hwnd, (HMENU) ID_LARGER, hInst, NULL) ; return 0 ; case WM_SIZE : cxClient = LOWORD (lParam) ; cyClient = HIWORD (lParam) ; // Move the buttons to the new center MoveWindow (hwndSmaller,cxClient/2-3*BTN_WIDTH/2, cyClient/2-BTN_HEIGHT/2,BTN_WIDTH, BTN_HEIGHT,TRUE); MoveWindow (hwndLarger,cxClient/2+BTN_WIDTH/2,cyClient/2-BTN_HEIGHT/2,BTN_WIDTH, BTN_HEIGHT,TRUE); return 0 ; case WM_COMMAND : GetWindowRect (hwnd, &rc) ; // Make the window 10% smaller or larger switch (wParam) { case ID_SMALLER : rc.left += cxClient / 20 ; rc.right -= cxClient / 20 ; rc.top += cyClient / 20 ; rc.bottom -= cyClient / 20 ; break ;

  17. case ID_LARGER : rc.left -= cxClient / 20 ; rc.right += cxClient / 20 ; rc.top -= cyClient / 20 ; rc.bottom += cyClient / 20 ; break ; } MoveWindow (hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE) ; return 0 ; case WM_DRAWITEM : pdis = (LPDRAWITEMSTRUCT) lParam ; // Fill area with white and frame it black FillRect (pdis->hDC, &pdis->rcItem,(HBRUSH) GetStockObject (WHITE_BRUSH)) ; FrameRect (pdis->hDC, &pdis->rcItem,(HBRUSH) GetStockObject (BLACK_BRUSH)) ; // Draw inward and outward black triangles cx = pdis->rcItem.right - pdis->rcItem.left ; cy = pdis->rcItem.bottom - pdis->rcItem.top ; switch (pdis->CtlID) { case ID_SMALLER : pt[0].x = 3 * cx / 8 ; pt[0].y = 1 * cy / 8 ; pt[1].x = 5 * cx / 8 ; pt[1].y = 1 * cy / 8 ; pt[2].x = 4 * cx / 8 ; pt[2].y = 3 * cy / 8 ; Triangle (pdis->hDC, pt) ; pt[0].x = 7 * cx / 8 ; pt[0].y = 3 * cy / 8 ; pt[1].x = 7 * cx / 8 ; pt[1].y = 5 * cy / 8 ; pt[2].x = 5 * cx / 8 ; pt[2].y = 4 * cy / 8 ; Triangle (pdis->hDC, pt) ; pt[0].x = 5 * cx / 8 ; pt[0].y = 7 * cy / 8 ; pt[1].x = 3 * cx / 8 ; pt[1].y = 7 * cy / 8 ; pt[2].x = 4 * cx / 8 ; pt[2].y = 5 * cy / 8 ; Triangle (pdis->hDC, pt) ; pt[0].x = 1 * cx / 8 ; pt[0].y = 5 * cy / 8 ; pt[1].x = 1 * cx / 8 ; pt[1].y = 3 * cy / 8 ; pt[2].x = 3 * cx / 8 ; pt[2].y = 4 * cy / 8 ; Triangle (pdis->hDC, pt) ; break ;

  18. case ID_LARGER : pt[0].x = 5 * cx / 8 ; pt[0].y = 3 * cy / 8 ; pt[1].x = 3 * cx / 8 ; pt[1].y = 3 * cy / 8 ; pt[2].x = 4 * cx / 8 ; pt[2].y = 1 * cy / 8 ; Triangle (pdis->hDC, pt) ; pt[0].x = 5 * cx / 8 ; pt[0].y = 5 * cy / 8 ; pt[1].x = 5 * cx / 8 ; pt[1].y = 3 * cy / 8 ; pt[2].x = 7 * cx / 8 ; pt[2].y = 4 * cy / 8 ; Triangle (pdis->hDC, pt) ; pt[0].x = 3 * cx / 8 ; pt[0].y = 5 * cy / 8 ; pt[1].x = 5 * cx / 8 ; pt[1].y = 5 * cy / 8 ; pt[2].x = 4 * cx / 8 ; pt[2].y = 7 * cy / 8 ; Triangle (pdis->hDC, pt) ; pt[0].x = 3 * cx / 8 ; pt[0].y = 3 * cy / 8 ; pt[1].x = 3 * cx / 8 ; pt[1].y = 5 * cy / 8 ; pt[2].x = 1 * cx / 8 ; pt[2].y = 4 * cy / 8 ; Triangle (pdis->hDC, pt) ; break ; } // Invert the rectangle if the button is selected if (pdis->itemState & ODS_SELECTED) InvertRect (pdis->hDC, &pdis->rcItem) ; // Draw a focus rectangle if the button has the focus if (pdis->itemState & ODS_FOCUS) { pdis->rcItem.left += cx / 16 ; pdis->rcItem.top += cy / 16 ; pdis->rcItem.right -= cx / 16 ; pdis->rcItem.bottom -= cy / 16 ; DrawFocusRect (pdis->hDC, &pdis->rcItem) ; } return 0 ; case WM_DESTROY : PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; }

  19. 9. BS_OWNERDRAW 스타일 단추 • 단추는 다시 표시되어야 할 때마다 자신의 부모 윈도우에게 WM_DRAWITEM메시지를 전달한다. • WM_DRAWITEM메시지를 처리하는 동안 lParam에는 DRAWITEMSTRUCT구조체의 포인터를 return한다. • hDC : 단추에 대한 DC • rcItem : 단추 크기를 제공한느 RECT구조체 • CtlID : 컨트롤 윈도우ID • itemState : 단추가 눌린 상태인지 또는 입력 포커스를 가지고 있는지를 나타낸다.ODS_SELECT,ODS_FOCUS • Progrmming Windows Page 451 참조

  20. 10. 정적 클래스 • 마우스나 키보드 입력을 받지 않으며, 부모 윈도우에 WM_COMMAND메시지를 전송하지 않는다. • 정적 자식 윈도우 위로 마우스를 옮기거나 클릭 할 때, 자식 윈도우는 WM_NCHITTEST메시지를 가로채고, HTTRANSPARENT를 윈도우에 반환한다. • SS_LEFT,SS_RIGHT,SS_CENTER를 포함하여 문자열을 정렬

  21. 11. 스크롤 바 클래스 • 스크롤 바 컨트롤은 부모 윈도우에WM_COMMAND를 보내지 않는 대신, 윈도우 스크롤 바처럼 WM_VSCROLL과WM_HSCROLL메시지를 보낸다. • 스크롤 바 메시지를 처리할 때, • lParam 매개 변수로 윈도우 스크롤 바 컨트롤과 컨트롤 스크롤 바 사이를 구별할 수 있다. • 컨트롤 스크롤 바 : • lParam 값 : 윈도우의 핸들 • hwndScrollBar = (HWND)lParam; • 윈도우 스크롤 바 : • lParam 값 : 0 • wParam : • nScrollCode = (int)LOWORD(wParam); • nPos = (short int)HIWORD(wParam);

  22. 11. 스크롤 바 클래스 Value Description SB_BOTTOM Scrolls to the lower right SB_ENDSCROLL Ends scroll SB_LINEDOWN Scrolls one line down SB_LINEUP Scrolls one line up SB_PAGEDOWN Scrolls one page down SB_PAGEUP Scrolls one page up SB_THUMBPOSITION The user has dragged the scroll box (thumb) and released the mouse button. The nPos parameter indicates the position of the scroll box at the end of the drag operation. SB_THUMBTRACK The user is dragging the scroll box. This message is sent repeatedly until the user releases the mouse button. The nPos parameter indicates the position that the scroll box has been dragged to. SB_TOP Scrolls to the upper left • SetScrollRange(hwndScroll,SB_CTL,iMin,iMax,bRedraw); • SetScrollPos(hwndScroll,SB_CTL,iPos,bRedraw); • SetScrollInfo(hwndScroll,SB_CTL,&si,bRedraw); • 윈도우 스크롤 바는 • 첫번째 매개변수로 메인 윈도우의 핸들, • 두번째 매개변수로 SB_VERT,SB_HORZ를 사용

  23. /*---------------------------------------- COLORS1.C -- Colors Using Scroll Bars (c) Charles Petzold, 1998 ----------------------------------------*/ #include <windows.h> LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; LRESULT CALLBACK ScrollProc (HWND, UINT, WPARAM, LPARAM) ; int idFocus ; WNDPROC OldScroll[3] ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("Colors1") ; 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 = CreateSolidBrush (0) ; wndclass.lpszMenuName = NULL ; wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass)) { MessageBox (NULL, TEXT ("This program requires Windows NT!"),szAppName, MB_ICONERROR) ; return 0 ; } hwnd = CreateWindow (szAppName, TEXT ("Color Scroll"),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 ; }

  24. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static COLORREF crPrim[3] = { RGB (255, 0, 0), RGB (0, 255, 0), RGB (0, 0, 255) } ; static HBRUSH hBrush[3], hBrushStatic ; static HWND hwndScroll[3], hwndLabel[3], hwndValue[3], hwndRect ; static int color[3], cyChar ; static RECT rcColor ; static TCHAR * szColorLabel[] = { TEXT ("Red"), TEXT ("Green"), TEXT ("Blue") } ; HINSTANCE hInstance ; int i, cxClient, cyClient ; TCHAR szBuffer[10] ; switch (message) { case WM_CREATE : hInstance = (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE) ; // Create the white-rectangle window against which the // scroll bars will be positioned. The child window ID is 9. hwndRect = CreateWindow (TEXT ("static"), NULL, WS_CHILD | WS_VISIBLE | SS_WHITERECT, 0, 0, 0, 0, hwnd, (HMENU) 9, hInstance, NULL) ; for (i = 0 ; i < 3 ; i++) { // The three scroll bars have IDs 0, 1, and 2, with // scroll bar ranges from 0 through 255. hwndScroll[i] = CreateWindow (TEXT ("scrollbar"), NULL, WS_CHILD | WS_VISIBLE | WS_TABSTOP | SBS_VERT, 0, 0, 0, 0, hwnd, (HMENU) i, hInstance, NULL) ; SetScrollRange (hwndScroll[i], SB_CTL, 0, 255, FALSE) ; SetScrollPos (hwndScroll[i], SB_CTL, 0, FALSE) ; // The three color-name labels have IDs 3, 4, and 5, // and text strings "Red", "Green", and "Blue". hwndLabel [i] = CreateWindow (TEXT ("static"), szColorLabel[i], WS_CHILD | WS_VISIBLE | SS_CENTER, 0, 0, 0, 0, hwnd, (HMENU) (i + 3), hInstance, NULL) ; // The three color-value text fields have IDs 6, 7, // and 8, and initial text strings of "0". hwndValue [i] = CreateWindow (TEXT ("static"), TEXT ("0"),WS_CHILD | WS_VISIBLE | SS_CENTER, 0, 0, 0, 0,hwnd, (HMENU) (i + 6), hInstance, NULL) ; OldScroll[i] = (WNDPROC) SetWindowLong (hwndScroll[i], GWL_WNDPROC, (LONG) ScrollProc) ; hBrush[i] = CreateSolidBrush (crPrim[i]) ; } hBrushStatic = CreateSolidBrush (GetSysColor (COLOR_BTNHIGHLIGHT)) ; cyChar = HIWORD (GetDialogBaseUnits ()) ; return 0 ;

  25. case WM_SIZE : cxClient = LOWORD (lParam) ; cyClient = HIWORD (lParam) ; SetRect (&rcColor, cxClient / 2, 0, cxClient, cyClient) ; MoveWindow (hwndRect, 0, 0, cxClient / 2, cyClient, TRUE) ; for (i = 0 ; i < 3 ; i++) { MoveWindow (hwndScroll[i],(2 * i + 1) * cxClient / 14, 2 * cyChar,cxClient / 14, cyClient - 4 * cyChar, TRUE) ; MoveWindow (hwndLabel[i],(4 * i + 1) * cxClient / 28, cyChar / 2,cxClient / 7, cyChar, TRUE) ; MoveWindow (hwndValue[i],(4 * i + 1) * cxClient / 28, cyClient - 3 * cyChar / 2,cxClient / 7, cyChar, TRUE) ; } SetFocus (hwnd) ; return 0 ; case WM_SETFOCUS : SetFocus (hwndScroll[idFocus]) ; return 0 ; case WM_VSCROLL : i = GetWindowLong ((HWND) lParam, GWL_ID) ; switch (LOWORD (wParam)) { case SB_PAGEDOWN :color[i] += 15 ;break; case SB_LINEDOWN :color[i] = min (255, color[i] + 1) ;break ; case SB_PAGEUP :color[i] -= 15 ;; break; case SB_LINEUP :color[i] = max (0, color[i] - 1) ;break ; case SB_TOP : color[i] = 0 ; break ; case SB_BOTTOM :color[i] = 255 ;break ; case SB_THUMBPOSITION : case SB_THUMBTRACK :color[i] = HIWORD (wParam) ;break ; default :break ; } SetScrollPos (hwndScroll[i], SB_CTL, color[i], TRUE) ; wsprintf (szBuffer, TEXT ("%i"), color[i]) ; SetWindowText (hwndValue[i], szBuffer) ; DeleteObject ((HBRUSH)SetClassLong (hwnd, GCL_HBRBACKGROUND, (LONG) CreateSolidBrush (RGB (color[0], color[1], color[2])))) ; InvalidateRect (hwnd, &rcColor, TRUE) ; return 0 ; case WM_CTLCOLORSCROLLBAR : i = GetWindowLong ((HWND) lParam, GWL_ID) ; return (LRESULT) hBrush[i] ;

  26. case WM_CTLCOLORSTATIC : i = GetWindowLong ((HWND) lParam, GWL_ID) ; if (i >= 3 && i <= 8) // static text controls { SetTextColor ((HDC) wParam, crPrim[i % 3]) ; SetBkColor ((HDC) wParam, GetSysColor (COLOR_BTNHIGHLIGHT)); return (LRESULT) hBrushStatic ; } break ; case WM_SYSCOLORCHANGE : DeleteObject (hBrushStatic) ; hBrushStatic = CreateSolidBrush (GetSysColor (COLOR_BTNHIGHLIGHT)) ; return 0 ; case WM_DESTROY : DeleteObject ((HBRUSH) SetClassLong (hwnd, GCL_HBRBACKGROUND, (LONG)GetStockObject (WHITE_BRUSH))) ; for (i = 0 ; i < 3 ; i++) DeleteObject (hBrush[i]) ; DeleteObject (hBrushStatic) ; PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } LRESULT CALLBACK ScrollProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { int id = GetWindowLong (hwnd, GWL_ID) ; switch (message) { case WM_KEYDOWN : if (wParam == VK_TAB) SetFocus (GetDlgItem (GetParent (hwnd),(id + (GetKeyState (VK_SHIFT) < 0 ? 2 : 1)) % 3)) ; break ; case WM_SETFOCUS : idFocus = id ; break ; } return CallWindowProc (OldScroll[id], hwnd, message, wParam, lParam) ; }

  27. 12. 윈도우 서브클래싱(SubClassing) • 스크롤 바 컨트롤에 대한 윈도우 프로시저는 Window내부 어느 곳인가에 있다. • GWL_WNDPROC를 사용하여 GetWindowLong을 호출하여 윈도우 프로시저에 대한 주소를 얻을 수 있다. • SetWindowLong을 이용하여 윈도우 프로시저를 설정할 수도 있다. • OldScroll[I] = (WNDPROC)SetWindowLong (hwndScroll[I],GWL_WNDPROC,(LONG) ScrollProc)); • WM_CTLCOLORSCROLLBAR • 스크롤 바가 자신이 그려져야 할 때 부모 윈도우에게 이 메시지를 보낸다. • hdcSB = (HDC)wParam; • hwndSB = (HWND)lParam; • 스크롤 바의 배경을 칠할 브러쉬의 핸들을 리턴한다.

  28. /*------------------------------------------------------- POPPAD1.C -- Popup Editor using child window edit box (c) Charles Petzold, 1998 -------------------------------------------------------*/ #include <windows.h> #define ID_EDIT 1 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); TCHAR szAppName[] = TEXT ("PopPad1") ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) { 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 ("This program requires Windows NT!"),szAppName, MB_ICONERROR) ; 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 ; }

  29. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hwndEdit ; switch (message) { case WM_CREATE : hwndEdit = CreateWindow (TEXT ("edit"), NULL,WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_BORDER | ES_LEFT | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,0, 0, 0, 0, hwnd, (HMENU) ID_EDIT,((LPCREATESTRUCT) lParam) -> hInstance, NULL) ; return 0 ; case WM_SETFOCUS : SetFocus (hwndEdit) ; return 0 ; case WM_SIZE : MoveWindow (hwndEdit, 0, 0, LOWORD (lParam), HIWORD (lParam), TRUE) ; return 0 ; case WM_COMMAND : if (LOWORD (wParam) == ID_EDIT) if (HIWORD (wParam) == EN_ERRSPACE || HIWORD (wParam) == EN_MAXTEXT) MessageBox (hwnd, TEXT ("Edit control out of space."),szAppName, MB_OK | MB_ICONSTOP) ; return 0 ; case WM_DESTROY : PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; }

  30. 13. 에디트 클래스 스타일 • 에디트 컨트롤은 부모 윈도우에 WM_COMMAND메시지를 보낸다. • LOWORD(wParam) 자식 윈도우 • HIWORD(wParam) 알림 코드 • lParam 자식 윈도우 핸들 • 기본값으로 에디트 컨트롤은 하나의 줄을 갖는다. • 여러줄 : ES_MULTILINE • 자동적으로 수평 방향으로 스크롤하려면 • ES_AUTOHSCROLL • 입력 포커스를 잃은 때에도 계속 하이라이트되게 하려면 • ES_NOHIDESEL • 인식 코드 • EN_SETFOCUS : 컨트롤이 입력 포커스를 얻었다. • EN_KILLFOCUS : 컨트롤이 입력 포커스를 잃었다. • EN_CHANGE : 컨트롤의 내용이 변경될 것이다. • EN_UPDATE : 컨트롤의 내용이 변경되었다. • EN_ERRSPACE : 컨트롤의 여백이 없다. • EN_MAXTEXT : 컨트롤에 삽입할 공간이 없다. • EN_HSCROLL : 컨트롤의 수평 스크롤 바가 클릭 되었다. • EN_VSCROLL : 컨트롤의 수직 스크롤 바가 클릭 되었다.

  31. 14. 에디트 컨트롤에 메시지를 전송하기 • 현재 선택된 것을 자르고,복사하고,지우기 • SendMessage(hwndEdit,WM_CUT,0,0); • SendMessage(hwndEdit,WM_COPY,0,0); • SendMessage(hwndEdit,WM_CLEAR,0,0); • SendMessage(hwndEdit,WM_PASTE,0,0); • 현재 선택의 시작과 끝을 얻을 수 있다. • SendMessage(hwndEdit,EM_GETSEL,(WPARAM) &iStart, (LPARAM) &iEND); • 텍스트를 선택 • SendMEssage(hwndEdit,EM_SETSEL,iStart,iEnd); • 다른 텍스트를 교체 • SendMEssage(hwndEdit,EM_REPLACESEL,0,(LPARAM)szString); • 멀티라인 에디트 컨트롤에서 줄의 수 • iCount = SendMessage(hwndEdit,EM_GETLINECOUNT,0,0); • 줄 길이를 얻을 수 있다. • iLength = SendMessage(hwndEdit,EM_LINELENGTH,iLine,0); • 줄 자체를 버퍼에 복사 • iLength = SendMessage(hwndEdit,EM_GETLINE,iLine, (LPARAM) szBuffer);

  32. 15. 목록 상자 스타일 • 윈도우 클래스로는 listbox를 사용 • 기본 목록 상자 스타일을 부모에게 WM_COMMAND를 보내지 않는다. • 목록 상자 스타일 LBS_NOTIFY를 사용하여, WM_COMMAND메시지를 부모 윈도우가 받도록 해준다. • 다중 목록 상자를 만들려면 LBS_MULTIPLESEL스타일을 사용한다. • 새로운 항목이 스크롤 바 목록에 추가 될 때마다 자신을 갱신한다. LBS_NOREDRAW스타일을 포함하여 이것을 방지 • SendMessage를 사용하여 텍스트를 삽입 • SendMessage(hwndlist,LB_ADDSTRING,0,(LPARAM)szString); • SendMessage(hwndlist,LB_INSERTSTRING,iIndex,(LPARAM)szString); • SendMessage(hwndlist,LB_DELETESTRING,iIndex, 0); • 목록을 모두 삭제 • SendMessage(hwndlist,LB_RESETCONTENT,0, 0); • 컨트롤의 다시 그리기 플래그를 끄기 • SendMessage(hwndlist,WM_SETREDRAW,FALSE,0); • SendMessage(hwndlist,WM_SETREDRAW,TRUE,0);

  33. 15. 목록 상자 스타일

  34. 15. 목록 상자 스타일

  35. 15. 목록 상자 스타일

  36. 15. 목록 상자 스타일 • 항목 선택 및 추출하기 • 항목의 개수를 알아낸다. • iCount = SendMessage(hwndList,LB_GETCOUNT,0,0); • 해당 항목을 선택 • SendMessage(hwndList,LB_SETCURSEL,iIndex,0); • 항목의 첫 문자에 근거하여 항목을 선택 • iIndex = SendMessage(hwndList, LB_SELECTSTRING,iIndex, (LPARAM)szSearchString); • WPARAM으로 제공되는 iIndex는szSearchString과 부합되는 첫 문자를 가진 항목에 대한 검색이 시작될 때 인덱스값이다. • 부합되는 첫문자가 없으면 LB_ERR를 반환 • 현재 선택의 인덱스를 알아 낸다. • iIndex = SendMessage(hwndList,LB_GETCURSEL,0,0); • 어떤 문자열의 길이 리턴 • iLength = SendMessage(hwndList,LB_GETTEXTLEN, iIndex,0); • 항목을 텍스트 버퍼로 복사할 수 있다. • iLength = SendMessage(hwndList,LB_GETTEXT,iIndex, (LPARAM)szBuffer); • 다중 선택 목록에서는 LB_SETCURSEL, LB_GETCURSEL, LB_SELECTSTRING을 사용할 수 없다.

  37. 15. 목록 상자 스타일 • 다중 선택 목록에서 특정 항목의 선택 상태를 설정하기 위해 LB_SETSEL을 사용 • SendMessage(hwndList,LB_SETSEL,wParam,iIndex); • wParam => 취소 : 0, 선택은 0이 아닌 값 • 특정 항목의 선택 상태를 알려면 LB_GETSEL이용 • iSelect=SendMessage(hwndList,LB_GETSEL,iIndex,0); • iSelect : iIndex가 항목이 선택되어 있으면 0이 아닌 값 • 선택되어 있지 않으면 0으로 설정 • 목록 상자는 자신의 부모에게 WM_COMMAND를 보낸다. • LOWORD(wParam) : 자식 윈도우 ID • HIWORD(wPram) : 알림 코드 • LParam : 자식 윈도우 핸들 • 알림 코드 • LBN_ERRSPACE : • 목록 상자 컨트롤이 공간이 부족하다는 것을 가리킨다. • LBN_SELCHANGE • 현재 선택이 변경되었다는 것을 가리킨다. • 사용자가 하이라이트 목록 상자를 통해 이동시키고 Space bar키로 선택 상태를 토글하거나 마우스로 항목을 선택할 때 발생한다. • LBN_DBLCLK • 목록 상자 항목이 마우스로 더블 클릭 되었음을 가리킨다. • 윈도우 스타일이 LBS_NOTIFY일 경우에만BN_SELCHANGE,LBN_DBLCLK를 받을 수 있다.

  38. /*---------------------------------------- ENVIRON.C -- Environment List Box (c) Charles Petzold, 1998 ----------------------------------------*/ #include <windows.h> #define ID_LIST 1 #define ID_TEXT 2 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("Environ") ; 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) (COLOR_WINDOW + 1) ; wndclass.lpszMenuName = NULL ; wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass)) { MessageBox (NULL, TEXT ("This program requires Windows NT!"),szAppName, MB_ICONERROR) ; return 0 ; } hwnd = CreateWindow (szAppName, TEXT ("Environment List Box"),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 ; }

  39. void FillListBox (HWND hwndList) { int iLength ; TCHAR * pVarBlock, * pVarBeg, * pVarEnd, * pVarName ; pVarBlock = GetEnvironmentStrings () ; // Get pointer to environment block while (*pVarBlock) { if (*pVarBlock != '=') // Skip variable names beginning with '=' { pVarBeg = pVarBlock ; // Beginning of variable name while (*pVarBlock++ != '=') ; // Scan until '=' pVarEnd = pVarBlock - 1 ; // Points to '=' sign iLength = pVarEnd - pVarBeg ; // Length of variable name // Allocate memory for the variable name and terminating // zero. Copy the variable name and append a zero. pVarName = calloc (iLength + 1, sizeof (TCHAR)) ; CopyMemory (pVarName, pVarBeg, iLength * sizeof (TCHAR)) ; pVarName[iLength] = '\0' ; // Put the variable name in the list box and free memory. SendMessage (hwndList, LB_ADDSTRING, 0, (LPARAM) pVarName) ; free (pVarName) ; } while (*pVarBlock++ != '\0') ; // Scan until terminating zero } FreeEnvironmentStrings (pVarBlock) ; }

  40. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam) { static HWND hwndList, hwndText ; int iIndex, iLength, cxChar, cyChar ; TCHAR * pVarName, * pVarValue ; switch (message) { case WM_CREATE : cxChar = LOWORD (GetDialogBaseUnits ()) ; cyChar = HIWORD (GetDialogBaseUnits ()) ; // Create listbox and static text windows. hwndList = CreateWindow (TEXT ("listbox"), NULL,WS_CHILD | WS_VISIBLE | LBS_STANDARD, cxChar, cyChar * 3,cxChar * 16 + GetSystemMetrics (SM_CXVSCROLL),cyChar * 5, hwnd, (HMENU) ID_LIST,(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),NULL) ; hwndText = CreateWindow (TEXT ("static"), NULL,WS_CHILD | WS_VISIBLE | SS_LEFT, cxChar, cyChar, GetSystemMetrics (SM_CXSCREEN), cyChar,hwnd, (HMENU) ID_TEXT, (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),NULL) ; FillListBox (hwndList) ; return 0 ; case WM_SETFOCUS : SetFocus (hwndList) ; return 0 ; case WM_COMMAND : if (LOWORD (wParam) == ID_LIST && HIWORD (wParam) == LBN_SELCHANGE) { iIndex = SendMessage (hwndList, LB_GETCURSEL, 0, 0) ; iLength = SendMessage (hwndList, LB_GETTEXTLEN, iIndex, 0) + 1 ; pVarName = calloc (iLength, sizeof (TCHAR)) ; SendMessage (hwndList, LB_GETTEXT, iIndex, (LPARAM) pVarName) ; iLength = GetEnvironmentVariable (pVarName, NULL, 0) ; pVarValue = calloc (iLength, sizeof (TCHAR)) ; GetEnvironmentVariable (pVarName, pVarValue, iLength) ; SetWindowText (hwndText, pVarValue) ; free (pVarName) ; free (pVarValue) ; } return 0 ; case WM_DESTROY : PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; }

  41. 16. 파일 나열하기 • LB_DIR • 목록 상자를 파일 디렉토리 리스트와 옵션으로 서브 디렉토리와 유효한 디스크 드라이브로 채운다. • SendMessage(hwndList,LB_DIR,iAttr,(LPARAM)szFileSpec); • iAttr • 파일 속성 코드이다. • DDL_READWRITE : 일반 파일 • DDL_READONLY : 읽기 전용 • DDL_HIDDEN : 숨김 • DDL_SYSTEM : 시스템 • DDL_DIRECTORY : 하위 디렉토리 • DDL_ARCHIVE : 보관 bit가 설정된 파일 • DDL_DRIVES : 드라이브 문자 포함 • DDL_EXECLUSIVE : 독점 검색 전용 • lParam은 “*.*”같은 파일 지정 문자열에 대한 포인터

  42. /*--------------------------------------------- HEAD.C -- Displays beginning (head) of file (c) Charles Petzold, 1998 ---------------------------------------------*/ #include <windows.h> #define ID_LIST 1 #define ID_TEXT 2 #define MAXREAD 8192 #define DIRATTR (DDL_READWRITE | DDL_READONLY | DDL_HIDDEN | DDL_SYSTEM | DDL_DIRECTORY | DDL_ARCHIVE | DDL_DRIVES) #define DTFLAGS (DT_WORDBREAK | DT_EXPANDTABS | DT_NOCLIP | DT_NOPREFIX) LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; LRESULT CALLBACK ListProc (HWND, UINT, WPARAM, LPARAM) ; WNDPROC OldList ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("head") ; 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) (COLOR_BTNFACE + 1) ; wndclass.lpszMenuName = NULL ; wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass)) { MessageBox (NULL, TEXT ("This program requires Windows NT!"),szAppName, MB_ICONERROR) ; return 0 ; } hwnd = CreateWindow (szAppName, TEXT ("head"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, 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 ; }

  43. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static BOOL bValidFile ; static BYTE buffer[MAXREAD] ; static HWND hwndList, hwndText ; static RECT rect ; static TCHAR szFile[MAX_PATH + 1] ; HANDLE hFile ; HDC hdc ; int i, cxChar, cyChar ; PAINTSTRUCT ps ; TCHAR szBuffer[MAX_PATH + 1] ; switch (message) { case WM_CREATE : cxChar = LOWORD (GetDialogBaseUnits ()) ; cyChar = HIWORD (GetDialogBaseUnits ()) ; rect.left = 20 * cxChar ; rect.top = 3 * cyChar ; hwndList = CreateWindow (TEXT ("listbox"), NULL,WS_CHILDWINDOW | WS_VISIBLE | LBS_STANDARD, cxChar, cyChar * 3,cxChar * 13 + GetSystemMetrics (SM_CXVSCROLL),cyChar * 10,hwnd, (HMENU) ID_LIST,(HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),NULL) ; GetCurrentDirectory (MAX_PATH + 1, szBuffer) ; hwndText = CreateWindow (TEXT ("static"), szBuffer,WS_CHILDWINDOW | WS_VISIBLE | SS_LEFT, cxChar, cyChar, cxChar * MAX_PATH, cyChar,hwnd, (HMENU) ID_TEXT, (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE),NULL) ; OldList = (WNDPROC) SetWindowLong (hwndList, GWL_WNDPROC,(LPARAM) ListProc) ; SendMessage (hwndList, LB_DIR, DIRATTR, (LPARAM) TEXT ("*.*")) ; return 0 ; case WM_SIZE : rect.right = LOWORD (lParam) ; rect.bottom = HIWORD (lParam) ; return 0 ; case WM_SETFOCUS : SetFocus (hwndList) ; return 0 ;

  44. case WM_COMMAND : if (LOWORD (wParam) == ID_LIST && HIWORD (wParam) == LBN_DBLCLK) { if (LB_ERR == (i = SendMessage (hwndList, LB_GETCURSEL, 0, 0))) break ; SendMessage (hwndList, LB_GETTEXT, i, (LPARAM) szBuffer) ; if (INVALID_HANDLE_VALUE != (hFile = CreateFile (szBuffer, GENERIC_READ, FILE_SHARE_READ, NULL,OPEN_EXISTING, 0, NULL))) { CloseHandle (hFile) ; bValidFile = TRUE ; lstrcpy (szFile, szBuffer) ; GetCurrentDirectory (MAX_PATH + 1, szBuffer) ; if (szBuffer [lstrlen (szBuffer) - 1] != '\\') lstrcat (szBuffer, TEXT ("\\")) ; SetWindowText (hwndText, lstrcat (szBuffer, szFile)) ; } else { bValidFile = FALSE ; szBuffer [lstrlen (szBuffer) - 1] = '\0' ; // If setting the directory doesn't work, maybe it's // a drive change, so try that. if (!SetCurrentDirectory (szBuffer + 1)) { szBuffer [3] = ':' ; szBuffer [4] = '\0' ; SetCurrentDirectory (szBuffer + 2) ; } // Get the new directory name and fill the list box. GetCurrentDirectory (MAX_PATH + 1, szBuffer) ; SetWindowText (hwndText, szBuffer) ; SendMessage (hwndList, LB_RESETCONTENT, 0, 0) ; SendMessage (hwndList, LB_DIR, DIRATTR,(LPARAM) TEXT ("*.*")) ; } InvalidateRect (hwnd, NULL, TRUE) ; } return 0 ;

  45. case WM_PAINT : if (!bValidFile) break ; if (INVALID_HANDLE_VALUE == (hFile = CreateFile (szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL))) { bValidFile = FALSE ; break ; } ReadFile (hFile, buffer, MAXREAD, &i, NULL) ; CloseHandle (hFile) ; hdc = BeginPaint (hwnd, &ps) ; SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ; SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT)) ; SetBkColor (hdc, GetSysColor (COLOR_BTNFACE)) ; // Assume the file is ASCII DrawTextA (hdc, buffer, i, &rect, DTFLAGS) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY : PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } LRESULT CALLBACK ListProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { if (message == WM_KEYDOWN && wParam == VK_RETURN) SendMessage (GetParent (hwnd), WM_COMMAND, MAKELONG (1, LBN_DBLCLK), (LPARAM) hwnd) ; return CallWindowProc (OldList, hwnd, message, wParam, lParam) ; }

  46. 17. OWNERDRAW • 오너 드로우에 사용되는 메시지에는 두 가지가 있다. • WM_MEASUREITEM • 이 메시지는 리스트 박스의 항목이 그려지기 전에 항목의 크기를 부모 윈도우에게 물어보기 위해 사용한다. typedef struct MEASUREITEMSTRUCT  { UINT  CtlType; UINT  CtlID; UINT  itemID; UINT  itemWidth; UINT  itemHeight; ULONG_PTR  itemData; } MEASUREITEMSTRUCT

  47. 17. OWNERDRAW • 이 메시지를 처리했으면 반드시 TRUE를 리턴해 주어야 한다.

  48. 17. OWNERDRAW • WM_DRAWITEM • 이 메시지의 wParam으로는 컨트롤의 ID가 전달되며, lParam에는 DRAWITEMSTRUCT의 포인터가 전달된다. typedef struct tagDRAWITEMSTRUCT  { UINT  CtlType; UINT  CtlID; UINT  itemID; UINT  itemAction; UINT  itemState; HWND  hwndItem; HDC  hDC; RECT  rcItem; ULONG_PTR  itemData; } DRAWITEMSTRUCT;

  49. 17. OWNERDRAW

  50. 17. OWNERDRAW

More Related