《windows程序设计》滚动条中WM_SIZE消息问题

ztwz 2005-04-15 11:47:55
下面这些代码是书中自带的。问题我注释在//后面了。

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static int cxChar, cxCaps, cyChar, cxClient, cyClient, iMaxWidth ;
HDC hdc ;
int i, x, y, iVertPos, iHorzPos, iPaintBeg, iPaintEnd ;
PAINTSTRUCT ps ;
SCROLLINFO si ;
TCHAR szBuffer[10] ;
TEXTMETRIC tm ;

switch (message)
{
case WM_CREATE:
hdc = GetDC (hwnd) ;

GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmAveCharWidth ;
cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * cxChar / 2 ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;

ReleaseDC (hwnd, hdc) ;

iMaxWidth = 40 * cxChar + 22 * cxCaps ;
return 0 ;
////////////////////////////////////////////////////////////////////////////////
//书中说WM_SIZE消息是在客户区大小被改变时调用,难到滑动滚动条也有WM_SIZE消息?
//在这个程序中是什么事件引起windows发送WM_SIZE消息的?
///////////////////////////////////////////////////////////////////////////////////////
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;

// Set vertical scroll bar range and page size

si.cbSize = sizeof (si) ;
si.fMask = SIF_RANGE | SIF_PAGE ;
si.nMin = 0 ;
si.nMax = NUMLINES - 1 ;
si.nPage = cyClient / cyChar ;
SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;

// Set horizontal scroll bar range and page size

si.cbSize = sizeof (si) ;
si.fMask = SIF_RANGE | SIF_PAGE ;
si.nMin = 0 ;
si.nMax = 2 + iMaxWidth / cxChar ;
si.nPage = cxClient / cxChar ;
SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ;
return 0 ;

case WM_VSCROLL:
// Get all the vertial scroll bar information

si.cbSize = sizeof (si) ;
si.fMask = SIF_ALL ;
GetScrollInfo (hwnd, SB_VERT, &si) ;

// Save the position for comparison later on

iVertPos = si.nPos ;

switch (LOWORD (wParam))
{
case SB_TOP:
si.nPos = si.nMin ;
break ;

case SB_BOTTOM:
si.nPos = si.nMax ;
break ;

case SB_LINEUP:
si.nPos -= 1 ;
break ;

case SB_LINEDOWN:
si.nPos += 1 ;
break ;

case SB_PAGEUP:
si.nPos -= si.nPage ;
break ;

case SB_PAGEDOWN:
si.nPos += si.nPage ;
break ;

case SB_THUMBTRACK:
si.nPos = si.nTrackPos ;
break ;

default:
break ;
}

si.fMask = SIF_POS ;
SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;
GetScrollInfo (hwnd, SB_VERT, &si) ;

if (si.nPos != iVertPos)
{
ScrollWindow (hwnd, 0, cyChar * (iVertPos - si.nPos),
NULL, NULL) ;
UpdateWindow (hwnd) ;
}
return 0 ;

case WM_HSCROLL:

si.cbSize = sizeof (si) ;
si.fMask = SIF_ALL ;

GetScrollInfo (hwnd, SB_HORZ, &si) ;
iHorzPos = si.nPos ;

switch (LOWORD (wParam))
{
case SB_LINELEFT:
si.nPos -= 1 ;
break ;

case SB_LINERIGHT:
si.nPos += 1 ;
break ;

case SB_PAGELEFT:
si.nPos -= si.nPage ;
break ;

case SB_PAGERIGHT:
si.nPos += si.nPage ;
break ;

case SB_THUMBPOSITION:
si.nPos = si.nTrackPos ;
break ;

default :
break ;
}

si.fMask = SIF_POS ;
SetScrollInfo (hwnd, SB_HORZ, &si, TRUE) ;
GetScrollInfo (hwnd, SB_HORZ, &si) ;

if (si.nPos != iHorzPos)
{
ScrollWindow (hwnd, cxChar * (iHorzPos - si.nPos), 0,
NULL, NULL) ;
}
return 0 ;

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

si.cbSize = sizeof (si) ;
si.fMask = SIF_POS ;
GetScrollInfo (hwnd, SB_VERT, &si) ;
iVertPos = si.nPos ;

GetScrollInfo (hwnd, SB_HORZ, &si) ;
iHorzPos = si.nPos ;

iPaintBeg = max (0, iVertPos + ps.rcPaint.top / cyChar) ;
iPaintEnd = min (NUMLINES - 1,
iVertPos + ps.rcPaint.bottom / cyChar) ;

for (i = iPaintBeg ; i <= iPaintEnd ; i++)
{
x = cxChar * (1 - iHorzPos) ;
y = cyChar * (i - iVertPos) ;

TextOut (hdc, x, y,
sysmetrics.szLabel,
lstrlen (sysmetrics.szLabel)) ;

TextOut (hdc, x + 22 * cxCaps, y,
sysmetrics.szDesc,
lstrlen (sysmetrics.szDesc)) ;

SetTextAlign (hdc, TA_RIGHT | TA_TOP) ;

TextOut (hdc, x + 22 * cxCaps + 40 * cxChar, y, szBuffer,
wsprintf (szBuffer, TEXT ("%5d"),
GetSystemMetrics (sysmetrics.iIndex))) ;

SetTextAlign (hdc, TA_LEFT | TA_TOP) ;
}

EndPaint (hwnd, &ps) ;
return 0 ;

case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
...全文
233 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
szwpc 2005-04-16
  • 打赏
  • 举报
回复
当你用鼠标,改变窗口大小的时候(例如让窗口横向变化、纵向变化,或者横向纵向一起变化的时候),有这个消息的。
当按下鼠标,然后拖动窗口边框,然后放开鼠标的时候,就会产生一个WM_SIZE消息。当产生这个消息的时候,当然窗口客户区大小改变了,当然原来滚动条的控制范围就改变啦
所以就要处理这个消息了哇!
arrowcy 2005-04-16
  • 打赏
  • 举报
回复
那段wm_size处理的代码主要是为了在窗口大小改变时修改滚动条的长度等
arrowcy 2005-04-16
  • 打赏
  • 举报
回复
哦,应该是不影响
arrowcy 2005-04-16
  • 打赏
  • 举报
回复
从那段代码来看,滚动条要引发WM_SIZE消息
dog0883 2005-04-16
  • 打赏
  • 举报
回复
我在WM_SIZE里加了一个MessageBox函数,结果在程序运行的时候出现了MessageBox,而且还是两个。改变大小时出现一个Box,最小化出现一个,最小化后恢复大小时出现2个,而且能看到MessageBox得到响应前后滚动条的大小发生了变化
eric8231 2005-04-16
  • 打赏
  • 举报
回复
>> 在这个程序中是什么事件引起windows发送WM_SIZE消息的?

用户可以通过拖拽窗口的边框来改变“客户区”的大小啊~这时不就引起WM_SIZE消息了吗~然后每当客户区的大小改变时就调整滚动条。

程序没太细看,可能我理解得也不对:)
ztwz 2005-04-16
  • 打赏
  • 举报
回复
我认为这个程序是在窗口被创建的时候windows发送了一个WM_SIZE消息给程序!
书中说在调用CreateWindow函数的时候会产生一个WM_CREATE消息,我认为还会产生一个WM_SIZE消息,
不知道这样认为是否对的?
dog0883 2005-04-16
  • 打赏
  • 举报
回复
我用MessageBox又试了一下,当窗口的大小设置小到水平和垂直滚动条都会显示时,WM_SIZE消息在窗口创建时只发送一次,但是当大小设置得只有垂直滚动条才显示时,WM_SIZE消息发送了2次,而且2次中间还重绘了一次窗口。原因我也不知道,呵呵
ztwz 2005-04-16
  • 打赏
  • 举报
回复
我知道当窗口大小改变了windows就会发送一个WM_SIZE消息,但是在这个程序中我不改变窗口大小windows还是会发送一个WM_SIZE的消息是,WM_SIZE这个消息里是用来处理滚动条大小和取得客户区大小的!当我把case WM_SIZE:这个消息处理过程注释掉可以看到滚动条长度变小,说明在程序创建的时候就发送了一个WM_SIZE消息了!我就是想知道,在这个程序中是哪个地方让windows发送的WM_SIZE消息的!请大哥们指点一下,谢谢!
ztwz 2005-04-16
  • 打赏
  • 举报
回复
我在WM_CREATE和WM_SIZE中各加了个MessageBox,然后运行程序,在窗口还没创建出来的时候MessageBox弹出来了,说明程序运行到CreateWindow函数了,这时还没有绘制窗口,点确定后程序窗口和一个MessageBox弹出来了,说明窗口创建好了,但是窗口中还没有内容,说明程序没有运行到WM_PAINT这儿,而这儿的MessageBox应该是创建完成后windows又发送了一个WM_SIZE消息!点确定后窗口中的内容和滚动条,都出来了,而且又得弹出一个MessageBox,这个MessageBox是哪儿跑出来的我就猜不出来了:(
哪个大哥指点一下!
ztwz 2005-04-16
  • 打赏
  • 举报
回复
9494
为什么会是两个WM_SIZE消息?哪个大虾指点下是。

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧