windows程序设计书中的一个短例子,从中发现了一些隐私,来问问大家。

yiruirui0507 2011-01-27 05:40:31
#include<stdio.h>
#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)
{
/* char buf[30];
DWORD a=GetTickCount();
//printf("%d\n",a);
//wsprintf(buf,"time:%d",a);
itoa(a,buf,10);
MessageBox(NULL,buf,buf,0);
return 0;*/

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.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 ("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 ;
}
//void CALLBACK TimerProc(HWND hwnd,UINT message,UINT iTimerID,DWORD dwTimer)

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];
szBuffer[50];
static int cxChar,cyChar;
HDC hdc;
PAINTSTRUCT ps;
int i;
switch(message)
{
case WM_CREATE:
////WORD HIWORD(
///DWORD dwValue
//);
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;
case WM_PAINT:
InvalidateRect(hwnd,&rect,TRUE);
hdc=BeginPaint(hwnd,&ps);
SetBkColor(hdc,GetSysColor(COLOR_BTNFACE+1));
SetTextColor(hdc,GetSysColor(COLOR_WINDOWTEXT));
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,NULL,&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_KEYDOWN:
switch(wParam)
{
case VK_TAB:
MessageBox(NULL,TEXT("asd "),TEXT("xxx"),0);
}
return 0;
case WM_SYSCOLORCHANGE:
InvalidateRect(hwnd,NULL,TRUE);
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,message,wParam,lParam);
}

以上代码大家可以测试运行看看效果,当把窗口最小化或者挡住然后恢复显示的时候,发现那10个按钮变的乱七八糟的,因为窗口发生了重绘响应了WM_PAINT消息。这10个按钮是系统自定义的,然后控件==窗口==也有消息处理函数==有自己的WM_PAINT消息处理,对吧?哈哈,相信大家没争议
ScrollWindow(hwnd,0,-cyChar,NULL,&rect);//多注意这里,这里有问题
第三个参数我把变成NULL,表示整个客户区都属于滚动区域,但是第四个参数是裁剪区域才是真正决定谁滚动,所以这里只有rect区域内滚动,而后面的10个按钮不在裁剪区域,所以不需要滚动,但是事实上却不是如此,请问为什么?大家可以测试测试,10个按钮的排列变的乱七八槽,什么导致的?3Q!
...全文
321 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
lyingbo 2011-01-28
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 yiruirui0507 的回复:]
问题已经解决,回答者均有分数奉上,没弄过不满意结贴。
[/Quote]

恭喜LZ
zgsdzhaolanxiang1 2011-01-28
  • 打赏
  • 举报
回复
楼主怎么解决的呢?分享下。
sam263564 2011-01-28
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 edwardliqi 的回复:]
引用 14 楼 wltg2001 的回复:
引用 13 楼 edwardliqi 的回复:
新手问个问题哈

这个程序编译之后说我没有main入口啊。。。

一般情况下是建错了工程类型。


应该建什么类型的工程啊?
[/Quote]

你用的 console的工程类型吧 应该用WIN32 Application的工程类型建立工程
ProgrammerNO1 2011-01-28
  • 打赏
  • 举报
回复
有问题提是好事,问题解决了麻烦写下解决思路,伪代码也行!
edwardliqi 2011-01-28
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 wltg2001 的回复:]
引用 13 楼 edwardliqi 的回复:
新手问个问题哈

这个程序编译之后说我没有main入口啊。。。

一般情况下是建错了工程类型。
[/Quote]

应该建什么类型的工程啊?
wltg2001 2011-01-28
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 edwardliqi 的回复:]
新手问个问题哈

这个程序编译之后说我没有main入口啊。。。
[/Quote]
一般情况下是建错了工程类型。
edwardliqi 2011-01-28
  • 打赏
  • 举报
回复
新手问个问题哈

这个程序编译之后说我没有main入口啊。。。
oldmtn 2011-01-28
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 pady_pady 的回复:]
接分来了
[/Quote]...............
欣客 2011-01-28
  • 打赏
  • 举报
回复
怎么解决的 ?
oyljerry 2011-01-28
  • 打赏
  • 举报
回复
^_^,说说咋解决的.
fishion 2011-01-28
  • 打赏
  • 举报
回复
yiruirui0507 2011-01-28
  • 打赏
  • 举报
回复
ScrollWindow 对这个函数的理解不到位造成的,以前看的都是百度百科中文翻译,都说真正决定滚动区域的是第四个参数,仔细看了MSDN的英文才发现事实并非如此,第三个参数就是决定谁滚动,而第四个参数更是别有用意的,贴出MSDN解释:
lpRect [in]
Type: const RECT*

Pointer to the RECT structure specifying the portion of the client area to be scrolled. If this parameter is NULL, the entire client area is scrolled.

lpClipRect [in]
Type: const RECT*

Pointer to the RECT structure containing the coordinates of the clipping rectangle. Only device bits within the clipping rectangle are affected. Bits scrolled from the outside of the rectangle to the inside are painted; bits scrolled from the inside of the rectangle to the outside are not painted.

第四个参数可以结合第三个参数是使用,比如说第三个参数NULL表示客户区全部滚动,第四个参数&rect表示了客户区中间的一部分。则当整个客户区滚动的时候会出现以下情况:
一定有客户区的内容滚动到了这个&rect区域中,同时必有这个裁剪区域&rect中的内容滚出去了,滚动了客户区,参考Bits scrolled from the outside of the rectangle to the inside are painted; bits scrolled from the inside of the rectangle to the outside are not painted.
相信大家啊就明白这个参数的意义了。
回头看上述代码,
ScrollWindow(hwnd,0,-cyChar,NULL,&rect);//
整个客户区都会滚动,10个按钮在客户区吧,会滚动吧,这里没争议吧,然而ScrollWindow会触发WM_PAINT消息(这点大家可以随便证明)所以导致窗口要重绘的,
代码
case WM_PAINT:
InvalidateRect(hwnd,&rect,TRUE);
hdc=BeginPaint(hwnd,&ps);
SetBkColor(hdc,GetSysColor(COLOR_BTNFACE+1));
SetTextColor(hdc,GetSysColor(COLOR_WINDOWTEXT));
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;
可以看到没有重绘这10个已经被上移的按钮,所以必然会发生乱七八糟的,这个时候我们刷新一下窗口就看到效果了,移上去了。
也做了一个实验,因为WM_PAINT中有两句很关键
TextOut(hdc,24*cxChar,cyChar,szTop,lstrlen(szTop));
TextOut(hdc,24*cxChar,cyChar,szUnd,lstrlen(szUnd));
所以我定义了一个全局变量count并初始化为0,在WM_PAINT中if(count<3) 则TEXTOUT那两句
否则不画这两句,最后在WM_COMMAND中加上count++,来测试用户点击按钮导致WM_COMMAND(我测试的时候把WM_DRAWITEM注释掉了,为了方便)然后count自增,当小于3的时候窗口的客户区会输出TEXTOUT的那两句的内容的,当你在点击2才WM_COMMAND的时候,count=3了,此时不满足if(count<3)了,所以窗口上不会在继续出现TEXTOUT的那两句话了(这个其实已经证明了SCROLLWINDOW可以触发WM_PAINT消息了)。
主要的原因在于起床没把SCROLLWINDOW理解正确,结论:以后还是看MSDN好点。
rlexyum 2011-01-28
  • 打赏
  • 举报
回复
我也想知道。。。。。
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 guandq2106 的回复:]
引用 19 楼 q342210738 的回复:
问题已经解决,回答者均有分数奉上,没弄过不满意结贴。




楼主!膜拜
[/Quote]
3x
管哥的天下 2011-01-28
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 q342210738 的回复:]
问题已经解决,回答者均有分数奉上,没弄过不满意结贴。

[/Quote]


楼主!膜拜
yiruirui0507 2011-01-28
  • 打赏
  • 举报
回复
问题已经解决,回答者均有分数奉上,没弄过不满意结贴。
做鸡真好吃 2011-01-28
  • 打赏
  • 举报
回复
case WM_DRAWITEM:
case WM_COMMAND:
ScrollWindow(hwnd,0,-cyChar,NULL,&rect);//多注意这里,这里有问题
hdc=GetDC(hwnd);

-----------
//case WM_DRAWITEM: 这里注释掉,否则,每次WM_DRAWITEM消息都执行 WM_COMMAND,执行ScrollWindow,肯定有问题了。
case WM_COMMAND:
ScrollWindow(hwnd,0,-cyChar,NULL,&rect);//多注意这里,这里有问题
hdc=GetDC(hwnd);

16,471

社区成员

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

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

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