저는 서로 접촉하고 스크롤 할 수있는 여러 줄 편집 상자의 배열을 만드는 일종의 "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;
}
문제를 설명하기 위해 스크린 샷을 게시 할 수 있습니까? –
여기보실 수 있습니다 https://www.dropbox.com/sh/w56l81muubilldp/AABvVr9p7hNAa4l6FnnadSeQa?dl=0 – Alfred
사진을 볼 수있는 경우 하단에 "상자 29"와 회색 스트립이 표시되어야합니다. 상단 "Box 0"과 회색 스트립에서 회색 스트립이 이전 화면 컨텐츠로 오버레이됩니다 (자식 창에서 스크롤하는 경우에만 해당) – Alfred