2014-12-19 5 views
0

저는 서로 접촉하고 스크롤 할 수있는 여러 줄 편집 상자의 배열을 만드는 일종의 "multiline listview"를 구현했습니다.
주 창에서 작업하는 한 정상적으로 작동합니다. 그러나 어떤 이유로 나는 메인 윈도우의 Child 윈도우에서 그것을 할 필요가있다. 그리고 여기 저기로 스크롤 할 때 (이전 페이지의 추악한 나머지는 거기에 머물러있다.) 다시 위로 (같은 문제) 문제가있다. 하위 창에서 여러 줄의 "listview"가 아래쪽과 위쪽에서 문제가 발생합니다.

내가 뭘 잘못하고 있니?

코드 : 메인 윈도우

#include <windows.h> 
 
#include <stdio.h> 
 

 
#define ITEMS 30 /*number of items in list*/ 
 
#define HEIGHT 80 /*height of one item in pixels*/ 
 

 
static int curr_y=20;  // current y position to add next item 
 

 
static HWND hWnd;   // main windo handle 
 

 
static int cxClient;// width; 
 
static int cyClient;// height 
 

 
//------------------------------------------------------- 
 
void GetClientSize(HWND hWndParent) 
 
{ 
 
RECT rcl; 
 
    GetClientRect(hWndParent, &rcl); 
 
    cxClient = rcl.right; 
 
    cyClient = rcl.bottom; 
 
} 
 
//------------------------------------------------------- 
 
void Debug(TCHAR *Fmt, ...) 
 
{ 
 
    va_list argptr; 
 
    TCHAR buf[1000]; 
 
    va_start(argptr, Fmt); 
 
    vsprintf(buf, Fmt, argptr); 
 
    OutputDebugString(buf); 
 
    va_end(argptr); 
 
} 
 

 
//------------------------------------------------------- 
 
static void VScrollClient(HWND hwnd, int pos) 
 
{ 
 
    static int prev = 0; 
 
    int cy = prev - pos; 
 
    prev = pos; 
 
    if(cy) ScrollWindow(hwnd, 0, cy, NULL, NULL); 
 
} 
 
//------------------------------------------------------- 
 
static void CreateMultilineBox(HWND hwnd, int id) 
 
{ 
 
    GetClientSize(hwnd); 
 

 
    TCHAR buf[100]; 
 
    sprintf(buf,TEXT("This is\r\nBox %d"),id); 
 

 
    CreateWindow(TEXT("edit"), buf, 
 
       WS_VISIBLE | WS_CHILD | WS_BORDER | ES_MULTILINE , 
 
       50, curr_y, cxClient-100, HEIGHT+1, 
 
       hwnd, (HMENU)id+100, 
 
       GetModuleHandle(NULL), NULL); 
 

 
    curr_y += HEIGHT; 
 
} 
 
//------------------------------------------------------- 
 

 
static LRESULT 
 
CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
 
{ 
 
    switch(msg) 
 
    { 
 
     case WM_CREATE: 
 
      { 
 
      // setup scroll info (Min,Max,Page size) 
 
      SCROLLINFO si = {0}; 
 
      si.cbSize = sizeof(SCROLLINFO); 
 
      si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; 
 
      si.nPos = 0; 
 
      si.nMin = 0; 
 
      si.nMax = HEIGHT*ITEMS; 
 
      si.nPage = cyClient; 
 
      SetScrollInfo(hwnd, SB_VERT, &si, FALSE); 
 
      } 
 
     break; 
 

 
     case WM_SIZE: 
 
     { 
 
      int cyClient = HIWORD(lParam); 
 

 
      // update scroll page size 
 
      SCROLLINFO si = {0}; 
 
      si.cbSize = sizeof(SCROLLINFO); 
 
      si.fMask = SIF_PAGE; 
 
      si.nPage = cyClient; 
 
      SetScrollInfo(hwnd, SB_VERT, &si, TRUE); 
 

 
      // update window if maximized. 
 
      if(wParam == SIZE_MAXIMIZED) 
 
      { 
 
       si.fMask = SIF_RANGE | SIF_POS; 
 
       GetScrollInfo(hwnd, SB_VERT, &si); 
 
       VScrollClient(hwnd, si.nPos); 
 
      } 
 
      return 0; 
 
     } 
 

 
     case WM_VSCROLL: 
 
     { 
 
      SCROLLINFO si = {0}; 
 
      si.cbSize = sizeof(SCROLLINFO); 
 
      si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS; 
 
      GetScrollInfo(hwnd, SB_VERT, &si); 
 

 
      const int minPos = si.nMin; 
 
      const int maxPos = si.nMax - (si.nPage - HEIGHT); 
 
      int pos = -1; 
 

 
     Debug(TEXT("\n nMax=%d nPage=%d\n minPos=%d maxPos=%d nPos=%d"), 
 
       si.nMax, si.nPage, minPos, maxPos, si.nPos); 
 

 
      switch(LOWORD(wParam)) //code 
 
      { 
 
      case SB_LINEUP: 
 
       pos = max(si.nPos - HEIGHT, minPos); 
 
       break; 
 

 
      case SB_LINEDOWN: 
 
       pos = min(si.nPos + HEIGHT, maxPos); 
 
       break; 
 

 
      case SB_PAGEUP: 
 
       pos = max(si.nPos - (int)si.nPage, minPos); 
 
       break; 
 

 
      case SB_PAGEDOWN: 
 
       pos = min(si.nPos + (int)si.nPage, maxPos); 
 
       break; 
 

 
      case SB_TOP: 
 
       pos = minPos; 
 
       break; 
 

 
      case SB_BOTTOM: 
 
       pos = maxPos; 
 
       break; 
 

 
      case SB_THUMBTRACK: 
 
       if(si.nTrackPos>=maxPos-HEIGHT) pos=maxPos; 
 
       else pos = (si.nTrackPos/HEIGHT)*(HEIGHT); 
 
       break; 
 

 
      } 
 
      if(pos == -1) return 0; 
 
      SetScrollPos(hwnd, SB_VERT, pos, TRUE); 
 
      VScrollClient(hwnd, pos); 
 

 
      return 0; 
 
     } 
 
     case WM_KEYDOWN: 
 
     { 
 
      switch(wParam) // character code 
 
      { 
 
       case VK_UP: 
 
        SendMessage (hwnd, WM_VSCROLL, SB_LINEUP, 0); 
 
        break; 
 
       case VK_DOWN: 
 
        SendMessage (hwnd, WM_VSCROLL, SB_LINEDOWN,0); 
 
        break; 
 
       case VK_PRIOR: 
 
        SendMessage (hwnd, WM_VSCROLL, SB_PAGEUP, 0); 
 
        break; 
 
       case VK_NEXT: 
 
        SendMessage (hwnd, WM_VSCROLL, SB_PAGEDOWN, 0); 
 
        break; 
 
       case VK_HOME: 
 
        SendMessage (hwnd, WM_VSCROLL, SB_TOP, 0); 
 
        break; 
 
       case VK_END: 
 
        SendMessage (hwnd, WM_VSCROLL, SB_BOTTOM, 0); 
 
        break; 
 
       default: 
 
        return 0; 
 
      } 
 
      return 0; 
 
     } 
 

 
     case WM_PAINT: 
 
     { 
 
      PAINTSTRUCT ps; 
 
      HDC hdc = BeginPaint(hwnd, &ps); 
 

 
      EndPaint(hwnd, &ps); 
 
      ReleaseDC(hwnd, hdc); 
 
      return 0; 
 
     } 
 

 
     case WM_DESTROY: 
 

 
     PostQuitMessage(0); 
 
     break; 
 
    } 
 

 
    return DefWindowProcW(hwnd, msg, wParam, lParam); 
 
} 
 

 
//------------------------------------------------------- 
 

 
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
 
        PWSTR lpCmdLine, int nCmdShow) 
 
{ 
 
    MSG msg; 
 
    WNDCLASSW wc = {0}; 
 
    wc.lpszClassName = L"myclass"; 
 
    wc.hInstance  = hInstance; 
 
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); 
 
    wc.lpfnWndProc = WndProc; 
 
    wc.hCursor  = LoadCursor(0,IDC_ARROW); 
 

 

 
    RegisterClassW(&wc); 
 

 
    hWnd=CreateWindowW(wc.lpszClassName, L"test scrolling", 
 
       WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_VSCROLL, 
 
       10, 10, 900, 600, 0, 0, hInstance, 0); 
 

 
    if(!hWnd) return 0; 
 

 
    ShowWindow(hWnd, nCmdShow); 
 
    UpdateWindow(hWnd); 
 

 
    for(int i=0;i<ITEMS;i++) 
 
    { 
 
    CreateMultilineBox(hWnd, i); 
 
    } 
 

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

 
    return (int) msg.wParam; 
 
}

B의
a) srolling)

#include <windows.h> 
 
#include <stdio.h> 
 

 
#define ITEMS 30 /*number of items in list*/ 
 
#define HEIGHT 80 /*height of one item in pixels*/ 
 

 
static int curr_y=20;  // current y position to add next item 
 

 
static HWND hWnd;   // main windo handle 
 
static HWND hChild; 
 

 
static int cxClient;// width; 
 
static int cyClient;// height 
 

 
//------------------------------------------------------- 
 
void GetClientSize(HWND hWndParent) 
 
{ 
 
RECT rcl; 
 
    GetClientRect(hWndParent, &rcl); 
 
    cxClient = rcl.right; 
 
    cyClient = rcl.bottom; 
 
} 
 
//------------------------------------------------------- 
 
void Debug(TCHAR *Fmt, ...) 
 
{ 
 
    va_list argptr; 
 
    TCHAR buf[1000]; 
 
    va_start(argptr, Fmt); 
 
    vsprintf(buf, Fmt, argptr); 
 
    OutputDebugString(buf); 
 
    va_end(argptr); 
 
} 
 

 
//------------------------------------------------------- 
 
static void VScrollClient(HWND hwnd, int pos) 
 
{ 
 
    static int prev = 0; 
 
    int cy = prev - pos; 
 
    prev = pos; 
 
    if(cy) ScrollWindow(hwnd, 0, cy, NULL, NULL); 
 
} 
 
//------------------------------------------------------- 
 
static void CreateMultilineBox(HWND hwnd, int id) 
 
{ 
 
    GetClientSize(hwnd); 
 

 
    TCHAR buf[100]; 
 
    sprintf(buf,TEXT("This is\r\nBox %d"),id); 
 

 
    CreateWindow(TEXT("edit"), buf, 
 
       WS_VISIBLE | WS_CHILD | WS_BORDER | ES_MULTILINE , 
 
       50, curr_y, cxClient-100, HEIGHT+1, 
 
       hwnd, (HMENU)id+100, 
 
       GetModuleHandle(NULL), NULL); 
 

 
    curr_y += HEIGHT; 
 
} 
 
//------------------------------------------------------- 
 

 
static LRESULT 
 
CALLBACK ChildProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
 
{ 
 
    switch(msg) 
 
    { 
 
     case WM_CREATE: 
 
      { 
 
      // setup scroll info (Min,Max,Page size) 
 
      SCROLLINFO si = {0}; 
 
      si.cbSize = sizeof(SCROLLINFO); 
 
      si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; 
 
      si.nPos = 0; 
 
      si.nMin = 0; 
 
      si.nMax = HEIGHT*ITEMS; 
 
      si.nPage = cyClient; 
 
      SetScrollInfo(hwnd, SB_VERT, &si, FALSE); 
 
      } 
 
     break; 
 

 
     case WM_SIZE: 
 
     { 
 
      int cyClient = HIWORD(lParam); 
 

 
      // update scroll page size 
 
      SCROLLINFO si = {0}; 
 
      si.cbSize = sizeof(SCROLLINFO); 
 
      si.fMask = SIF_PAGE; 
 
      si.nPage = cyClient; 
 
      SetScrollInfo(hwnd, SB_VERT, &si, TRUE); 
 

 
      // update window if maximized. 
 
      if(wParam == SIZE_MAXIMIZED) 
 
      { 
 
       si.fMask = SIF_RANGE | SIF_POS; 
 
       GetScrollInfo(hwnd, SB_VERT, &si); 
 
       VScrollClient(hwnd, si.nPos); 
 
      } 
 
      return 0; 
 
     } 
 

 
     case WM_VSCROLL: 
 
     { 
 
      SCROLLINFO si = {0}; 
 
      si.cbSize = sizeof(SCROLLINFO); 
 
      si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_TRACKPOS; 
 
      GetScrollInfo(hwnd, SB_VERT, &si); 
 

 
      const int minPos = si.nMin; 
 
      const int maxPos = si.nMax - (si.nPage - HEIGHT); 
 
      int pos = -1; 
 

 
     Debug(TEXT("\n nMax=%d nPage=%d\n minPos=%d maxPos=%d nPos=%d"), 
 
       si.nMax, si.nPage, minPos, maxPos, si.nPos); 
 

 
      switch(LOWORD(wParam)) //code 
 
      { 
 
      case SB_LINEUP: 
 
       pos = max(si.nPos - HEIGHT, minPos); 
 
       break; 
 

 
      case SB_LINEDOWN: 
 
       pos = min(si.nPos + HEIGHT, maxPos); 
 
       break; 
 

 
      case SB_PAGEUP: 
 
       pos = max(si.nPos - (int)si.nPage, minPos); 
 
       break; 
 

 
      case SB_PAGEDOWN: 
 
       pos = min(si.nPos + (int)si.nPage, maxPos); 
 
       break; 
 

 
      case SB_TOP: 
 
       pos = minPos; 
 
       break; 
 

 
      case SB_BOTTOM: 
 
       pos = maxPos; 
 
       break; 
 

 
      case SB_THUMBTRACK: 
 
       if(si.nTrackPos>=maxPos-HEIGHT) pos=maxPos; 
 
       else pos = (si.nTrackPos/HEIGHT)*(HEIGHT); 
 
       break; 
 

 
      } 
 
      if(pos == -1) return 0; 
 
      SetScrollPos(hwnd, SB_VERT, pos, TRUE); 
 
      VScrollClient(hwnd, pos); 
 

 
      return 0; 
 
     } 
 
     case WM_KEYDOWN: 
 
     { 
 
      switch(wParam) // character code 
 
      { 
 
       case VK_UP: 
 
        SendMessage (hwnd, WM_VSCROLL, SB_LINEUP, 0); 
 
        break; 
 
       case VK_DOWN: 
 
        SendMessage (hwnd, WM_VSCROLL, SB_LINEDOWN,0); 
 
        break; 
 
       case VK_PRIOR: 
 
        SendMessage (hwnd, WM_VSCROLL, SB_PAGEUP, 0); 
 
        break; 
 
       case VK_NEXT: 
 
        SendMessage (hwnd, WM_VSCROLL, SB_PAGEDOWN, 0); 
 
        break; 
 
       case VK_HOME: 
 
        SendMessage (hwnd, WM_VSCROLL, SB_TOP, 0); 
 
        break; 
 
       case VK_END: 
 
        SendMessage (hwnd, WM_VSCROLL, SB_BOTTOM, 0); 
 
        break; 
 
       default: 
 
        return 0; 
 
      } 
 
      return 0; 
 
     } 
 

 
     case WM_PAINT: 
 
     { 
 
      PAINTSTRUCT ps; 
 
      HDC hdc = BeginPaint(hwnd, &ps); 
 

 
      EndPaint(hwnd, &ps); 
 
      ReleaseDC(hwnd, hdc); 
 
      return 0; 
 
     } 
 

 
     case WM_DESTROY: 
 

 
     PostQuitMessage(0); 
 
     break; 
 
    } 
 

 
    return DefWindowProcW(hwnd, msg, wParam, lParam); 
 

 
} /* ChildProc */ 
 

 
//============================================================================== 
 
static void ChildRegister(void) 
 
{ 
 
    WNDCLASS wc = { 0 }; 
 
    wc.style = 0; 
 
    wc.lpfnWndProc = ChildProc; 
 
    wc.hCursor = LoadCursor(NULL, IDC_ARROW); 
 
    wc.lpszClassName = TEXT("Child"); 
 
    RegisterClass(&wc); 
 
} 
 

 
//------------------------------------------------------- 
 
static HWND CreateChild(HWND hwnd) 
 
{ 
 
    GetClientSize(hwnd); 
 

 
    HWND hChild = CreateWindow(TEXT("Child"), NULL, 
 
     WS_VISIBLE | WS_CHILD | WS_VSCROLL, 
 
     0, 0, cxClient, cyClient, 
 
     hwnd, (HMENU)0, GetModuleHandle(NULL), NULL); 
 
    if(!hChild) 
 
    { 
 
     Debug(TEXT("\r\nCreate Cont failed, error=%d"),GetLastError()); 
 
    } 
 
    return hChild; 
 
} 
 

 
//------------------------------------------------------------ 
 

 
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
 
    WPARAM wParam, LPARAM lParam) 
 
{ 
 

 
    switch(msg) 
 
    { 
 
     case WM_CREATE: 
 

 
     break; 
 

 
     case WM_SIZE: 
 
     { 
 
      cxClient = LOWORD (lParam) ; // width 
 
      cyClient = HIWORD (lParam) ; // heigth 
 
      MoveWindow(hChild, 0, 0, cxClient, cyClient, TRUE); 
 
     break; 
 
     } 
 

 
     case WM_DESTROY: 
 

 
     PostQuitMessage(0); 
 
     break; 
 
    } 
 

 
    return DefWindowProcW(hwnd, msg, wParam, lParam); 
 
} 
 

 
//------------------------------------------------------- 
 
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
 
        PWSTR lpCmdLine, int nCmdShow) 
 
{ 
 
    MSG msg; 
 
    WNDCLASSW wc = {0}; 
 
    wc.lpszClassName = L"myclass"; 
 
    wc.hInstance  = hInstance; 
 
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); 
 
    wc.lpfnWndProc = WndProc; 
 
    wc.hCursor  = LoadCursor(0,IDC_ARROW); 
 

 

 
    RegisterClassW(&wc); 
 

 
    hWnd=CreateWindowW(wc.lpszClassName, L"test scrolling", 
 
       WS_OVERLAPPEDWINDOW | WS_VISIBLE, 
 
       10, 10, 900, 600, 0, 0, hInstance, 0); 
 

 
    if(!hWnd) return 0; 
 

 
    ShowWindow(hWnd, nCmdShow); 
 
    UpdateWindow(hWnd); 
 

 
    ChildRegister(); 
 
    hChild =CreateChild(hWnd); 
 
    if(!hChild) return 0; 
 
    SetFocus(hChild); 
 

 
    for(int i=0;i<ITEMS;i++) 
 
    { 
 
     CreateMultilineBox(hChild, i); 
 
    } 
 

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

 
    return (int) msg.wParam; 
 
}

+0

문제를 설명하기 위해 스크린 샷을 게시 할 수 있습니까? –

+0

여기보실 수 있습니다 https://www.dropbox.com/sh/w56l81muubilldp/AABvVr9p7hNAa4l6FnnadSeQa?dl=0 – Alfred

+0

사진을 볼 수있는 경우 하단에 "상자 29"와 회색 스트립이 표시되어야합니다. 상단 "Box 0"과 회색 스트립에서 회색 스트립이 이전 화면 컨텐츠로 오버레이됩니다 (자식 창에서 스크롤하는 경우에만 해당) – Alfred

답변

0

여기서 자식 윈도우 스크롤링은 내 솔루션 :

if ((pos == maxPos) || (pos == minPos) InvalidateRect (hWnd, NULL, TRUE);

+0

자식 창이 hChild에서 스크롤 할 때만 이것이 필요한 이유를 말해 줄 수 있습니까?하지만 주 창에서 직접 스크롤 할 때가 아닙니다. 직접? – Alfred