大家帮我看一下这个窗口函数

chaty 2003-08-20 11:39:56
大家帮我看一下这个窗口函数,有些地方不理解能否给我解释一下?


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) ;

// Save the width of the three columns

iMaxWidth = 40 * cxChar + 22 * cxCaps ;
return 0 ;

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 vertical 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 the position has changed, scroll the window and update it

if (si.nPos != iVertPos)
{
ScrollWindow (hwnd, 0, cyChar * (iVertPos - si.nPos),
NULL, NULL) ;
UpdateWindow(hwnd) ;//为什么这里要UpdateWindow?
}
return 0 ;

case WM_HSCROLL:
// Get all the vertical scroll bar information

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

// Save the position for comparison later on

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 ;
}
// Set the position and then retrieve it. Due to adjustments
// by Windows it may not be the same as the value set.

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

// If the position has changed, scroll the window

if (si.nPos != iHorzPos)
{
ScrollWindow (hwnd, cxChar * (iHorzPos - si.nPos), 0,
NULL, NULL) ;
//为什么这里不要UpdateWindow?
}
return 0 ;

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

// Get vertical scroll bar position

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

// Get horizontal scroll bar position
GetScrollInfo (hwnd, SB_HORZ, &si) ;
iHorzPos = si.nPos ;

// Find painting limits

iPaintBeg = iVertPos + ps.rcPaint.top / cyChar ;
iPaintEnd = iVertPos + ps.rcPaint.bottom / cyChar ;

for (i = iPaintBeg ; i <= iPaintEnd ; i++)
{ //~~去掉这个等号后,拖动滚动条时不能正确显示,刷新一次后又恢复正常,为什么?
x = cxChar * (1 - iHorzPos) ;
y = cyChar * (i - iVertPos) ;

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

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

SetTextAlign (hdc, TA_RIGHT | TA_TOP) ;

TextOut (hdc, x + 22 * cxCaps + 40 * cxChar, y, szBuffer,
wsprintf (szBuffer, TEXT ("%5d"),
GetSystemMetrics (sysmetrics[i].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) ;
}

...全文
119 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
chaty 2003-08-22
  • 打赏
  • 举报
回复
那文本窗口是怎么形成的?不是处理WM_PAINT的时候吧?
处理WM_PAINT的时候明明只画了客户区里的几行
不知道能不能找到ScrollWindow函数的代码?
joinrry 2003-08-21
  • 打赏
  • 举报
回复
长啊!!!!!!!!!!
chaty 2003-08-21
  • 打赏
  • 举报
回复
具体是这样的,
如果客户区的高度显示文本后会有半行的剩余即cyClient / cyChar不为整数,则向下滚动一行后,最下面的一行只有下半部分显示,上半部分空白。向上拖动可以正常显示
如果客户区的高度正好可以显示整数行文本,即cyClient / cyChar为整数,则向下滚动时也可以正常显示。
如果再少循环一次,即把循环条件改为for(i = iPaintBeg ; i < iPaintEnd - 1 ; i++)
则向上向下滚动都是空白没有任何显示。拖动滚动条很快移动的话,倒是会零星显示几行
不知道是不是调用了
ScrollWindow (hwnd, 0, cyChar * (iVertPos - si.nPos),
NULL, NULL) ;
的缘故?
chaty 2003-08-21
  • 打赏
  • 举报
回复
具体是这样的,
如果客户区的高度显示文本后留下半行的高度,那么向下滚动一行后,最下面的一行只有下半部分,上半部分空白。
如果客户区的高度正好可以显示整数行 即cyClient / cyChar为整数,则能正常显示。
但是向上滚动不会出现任何问题。
如果再少循环一次即把循环条件改为for(i = iPaintBeg ; i < iPaintEnd - 1; i++)则向上向下滚动都是空白,没有任何显示。不知道是不是因为调用了
ScrollWindow (hwnd, 0, cyChar * (iVertPos - si.nPos),
NULL, NULL) ;
的缘故?
hyeena 2003-08-21
  • 打赏
  • 举报
回复
这段代码我也看过,刚开始也不明白这滚动是怎么做的,后来终于
有点头绪了,其实可以这样看:有两个窗口,一个是文本窗口,一个是
我们看见的Client窗口,滚动其实就是把Client在文本窗口上面移动,使
我们可以看见文本的不同部分
chaty 2003-08-21
  • 打赏
  • 举报
回复
windows 代码是这样的啊
wangweintk 2003-08-20
  • 打赏
  • 举报
回复
这是一个窗口回调函数,分别处理了以下消息:
WM_CREATE
WM_SIZE
WM_VSCROLL
WM_HSCROLL
WM_PAINT
WM_DESTROY

拖动滚动条后,进入WM_VSCROLL(或WM_HSCROLL),然后进入WM_PAINT进行重绘。

到于你的"去掉这个等号后,拖动滚动条时不能正确显示,刷新一次后又恢复正常",在此处设一个断点,看看拖动后的iPaintBeg与iPaintEnd 是否相等,我判断是这样的,所以显示不正常,与你的滚动处理中有关。重新刷新后,不进入滚动处理,所以又正常了。

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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