蛋疼的SetROP2函数

zwb8848happy 2012-04-03 03:42:50

void DrawBoxOutline(HWND hwnd,POINT ptBeg,POINT ptEnd)
{
HDC hdc;
hdc=GetDC(hwnd);

SetROP2(hdc,R2_NOT);
SelectObject(hdc,GetStockObject(NULL_BRUSH));
Rectangle(hdc,ptBeg.x,ptBeg.y,ptEnd.x,ptEnd.y);

ReleaseDC(hwnd,hdc);
}

//窗口过程
case WM_LBUTTONDOWN:
fBlocking=TRUE;
ptBeg.x=ptEnd.x=LOWORD(lParam);
ptBeg.y=ptEnd.y=HIWORD(lParam);
DrawBoxOutline(hwnd,ptBeg,ptEnd);
return 0;

case WM_MOUSEMOVE:
if (fBlocking)
{
DrawBoxOutline(hwnd,ptBeg,ptEnd);
ptEnd.x=LOWORD(lParam);
ptEnd.y=HIWORD(lParam);
DrawBoxOutline(hwnd,ptBeg,ptEnd);
}
return 0;

case WM_LBUTTONUP:
if (fBlocking)
{
fBlocking=FALSE;
DrawBoxOutline(hwnd,ptBeg,ptEnd);
InvalidateRect(hwnd,NULL,TRUE);
}

return 0;

case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
DrawBoxOutline(hwnd,ptBeg,ptEnd);
EndPaint(hwnd,&ps);
return 0;


有两个问题想问问大家:
1、SetROP2函数是将画笔颜色设置为背景色的反色,WM_MOUSEMOVE中第一个DrawBoxOutline好像是用白色将刚刚画的黑色矩形重画一遍,以达到擦去效果。我想问大家,DrawBoxOutline中的SetROP2是静态的?为什么上次反转后为黑色,第二次反转就为白色?
2、这个程序很奇怪,如果画矩形后快速松开鼠标,屏幕上显示一个矩形。但是当我画完鼠标不松停留一段时间再松开鼠标,屏幕上无显示了!!
3、调试时我在WM_MOUSEMOVE那设了一个断点,当然其他地方也有断点,但是调试时总是在WM_MOUSEMOVE那循环,而且窗口一闪就不见了,不知为何??


各位大哥,小弟刚学windows程序设计,请大家指点一下!!!
不胜感激!!!
...全文
690 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
schlafenhamster 2012-04-06
  • 打赏
  • 举报
回复
有焦点的窗口可以接受到输入消息。
zwb8848happy 2012-04-05
  • 打赏
  • 举报
回复
嗯,受教了,可以讲讲父子窗口焦点切换到底怎么回事吗?
schlafenhamster 2012-04-04
  • 打赏
  • 举报
回复
像WM_PAINT等消息最好不要加断点,可以用OutputDebugString("xxxx");
因为断点会破坏窗口,又会发WM_PAINT。没法调试。
zwb8848happy 2012-04-04
  • 打赏
  • 举报
回复
是这样的,我在每个消息前都加断点,按F10调试后,先执行WM_PAINT消息,然后就跳到WM_MOUSEMOVE消息那,并且窗口一闪就没了,不给我点鼠标的机会。。。
schlafenhamster 2012-04-04
  • 打赏
  • 举报
回复
键盘控制?
case WM_LBUTTONDOWN怎么响应?
zwb8848happy 2012-04-04
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 的回复:]

第三个问题也许是因为只要鼠标移动就会响应,然后就会循环吧
[/Quote]

但是我调试的时候没用鼠标,就用键盘控制的
fordawn 2012-04-04
  • 打赏
  • 举报
回复
第三个问题也许是因为只要鼠标移动就会响应,然后就会循环吧
schlafenhamster 2012-04-04
  • 打赏
  • 举报
回复
"你是sdk,afxDump << point << "\n";不能用,使用:
OutputDebugString("Mouse move");
看看鼠标不动时有没有输出。"
SDK =software design kit 软件设计包。

case WM_MOUSEMOVE:
OutputDebugString("Mouse move");

if (fBlocking)
{
DrawBoxOutline(hWnd,ptBeg,ptEnd);
ptEnd.x=LOWORD(lParam);
ptEnd.y=HIWORD(lParam);
DrawBoxOutline(hWnd,ptBeg,ptEnd);
}
return 0;

zwb8848happy 2012-04-04
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 的回复:]

“WM_MOUSEMOVE那里循环”
鼠标移动就会进。
你是sdk,afxDump << point << "\n";不能用,使用:
OutputDebugString("Mouse move");
看看鼠标不动时有没有输出。
[/Quote]

有点看不懂,我不是用的MFC,我是用c语言调用WIN32 API来写的,还是初学者
schlafenhamster 2012-04-04
  • 打赏
  • 举报
回复
“WM_MOUSEMOVE那里循环”
鼠标移动就会进。
你是sdk,afxDump << point << "\n";不能用,使用:
OutputDebugString("Mouse move");
看看鼠标不动时有没有输出。
zwb8848happy 2012-04-04
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]

"调试时一直在WM_MOUSEMOVE那里循环"
不要使用Messagebox。
用afxDump << point << "\n";
[/Quote]

??
我没有在WM_MOUSEMOVE中用Messagebox啊。。。
而且整个窗口过程没有用过Messagebox。。。
schlafenhamster 2012-04-04
  • 打赏
  • 举报
回复
"调试时一直在WM_MOUSEMOVE那里循环"
不要使用Messagebox。
用afxDump << point << "\n";
zwb8848happy 2012-04-04
  • 打赏
  • 举报
回复
谢谢大家了!
不知怎么回事,今天再试我昨天写的代码竟然可以运行了!

清明节开挂了。。。

大家可以看看我第三个问题吗?
调试时一直在WM_MOUSEMOVE那里循环,并且窗口一闪就不见了。。。
schlafenhamster 2012-04-04
  • 打赏
  • 举报
回复
又试了试:
void DrawBoxOutline(HWND hwnd,POINT ptBeg,POINT ptEnd)
{
HDC hdc;
hdc=GetDC(hwnd);//R2_NOTXORPEN)
SetROP2(hdc,R2_NOT);
SelectObject(hdc,GetStockObject(NULL_BRUSH));
Rectangle(hdc,ptBeg.x,ptBeg.y,ptEnd.x,ptEnd.y);
ReleaseDC(hwnd,hdc);
}
在黑白按钮上效果是一样的。你可以试试,彩色按钮上如何。
schlafenhamster 2012-04-04
  • 打赏
  • 举报
回复
OutputDebugString()太多了会头都晕了。
最好分行:
OutputDebugString(TEXT("..LBChild 1..\n"));
有个警告!hwnd
MessageBox(0,TEXT("ERROR"),TEXT("ERROR"),MB_OK);
注册时hwnd还没有,用NULL或0。
zwb8848happy 2012-04-04
  • 打赏
  • 举报
回复
今天又发现一个问题,是关于父子窗口的输入焦点问题(Charles Petzold《windows程序设计》P245)
用OutPutDebugString调试了一下:
发现焦点这样切换:
1、点击不同的子窗口输出窗口输出:
..LBChild 1....Child_KillFocus....Child_SetFocus....Child_KillFocus....LBChild 2..

2、点击相同的子窗口:
..LBChild 1....LBChild 2..

3、当切换到另一个程序时:
..Child_KillFocus..

4、又进入到这个程序时:
..Child_SetFocus....Child_KillFocus....Parent_SetFocus..

感觉头都晕了,谁能梳理总结一下吗?

代码如下:

#include <Windows.h>

#define DIVISION 5

LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);
LRESULT CALLBACK ChildWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam);

int idFocus=0;
TCHAR szChildClass[]=TEXT("ChildClass");

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevHinstance,PSTR szCmdLine,int iCmdShow)
{
TCHAR szAppName[]=TEXT("Class");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;

wndclass.style=CS_HREDRAW|CS_VREDRAW;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.lpfnWndProc=WndProc;
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName=NULL;
wndclass.lpszClassName=szAppName;
wndclass.hInstance=hInstance;

if (!RegisterClass(&wndclass))
{
MessageBox(hwnd,TEXT("ERROR"),TEXT("ERROR"),MB_OK);
return 0;
}

wndclass.cbWndExtra=sizeof(long);
wndclass.lpfnWndProc=ChildWndProc;
wndclass.hIcon=NULL;
wndclass.lpszClassName=szChildClass;

RegisterClass(&wndclass);

hwnd=CreateWindow(szAppName,TEXT("First Program"),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;
}


LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
int x,y,cxBlock,cyBlock;
static HWND hwndChild[DIVISION][DIVISION];

switch (message)
{
case WM_CREATE:
for (x=0;x<DIVISION;x++)
{
for (y=0;y<DIVISION;y++)
{
hwndChild[x][y]=CreateWindow(szChildClass,NULL,WS_CHILD|WS_VISIBLE,0,0,0,0,hwnd,NULL,NULL,NULL);
}
}
return 0;

case WM_SIZE:
cxBlock=LOWORD(lParam)/DIVISION;
cyBlock=HIWORD(lParam)/DIVISION;

for (x=0;x<DIVISION;x++)
{
for (y=0;y<DIVISION;y++)
{
MoveWindow(hwndChild[x][y],x*cxBlock,y*cyBlock,cxBlock,cyBlock,TRUE);
}
}
return 0;

case WM_LBUTTONDOWN:
OutputDebugString(TEXT("..LBParent"));
MessageBeep(0);
return 0;


case WM_SETFOCUS: //On set-focus message,set focus to child window
SetFocus(GetDlgItem(hwnd,idFocus));
OutputDebugString(TEXT("..Parent_SetFocus.."));
return 0;


case WM_KEYDOWN: //On key-down message,possibly change the focus window
x=idFocus&0xFF;
y=idFocus>>8;

switch(wParam)
{
case VK_UP:
y--;
break;

case VK_DOWN:
y++;
break;

case VK_LEFT:
x--;
break;

case VK_RIGHT:
x++;
break;

case VK_PRIOR:
x=y=0;
break;

case VK_NEXT:
x=y=DIVISION-1;
break;

default:
return 0;
}

x=(x+DIVISION)%DIVISION;
y=(y+DIVISION)%DIVISION;

idFocus=y<<8|x;
SetFocus(GetDlgItem(hwnd,idFocus));
OutputDebugString(TEXT("..KeyParent"));
return 0;

case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,message,wParam,lParam);
}

LRESULT CALLBACK ChildWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;

switch(message)
{
case WM_CREATE:
SetWindowLong(hwnd,0,0);
return 0;

case WM_KEYDOWN: //send most key presses to the parent window
if (wParam!=VK_RETURN&&wParam!=VK_SPACE)
{
SendMessage(GetParent(hwnd),message,wParam,lParam);
return 0;
}


case WM_LBUTTONDOWN: //For Return and Space,fall through to toggle the square
SetWindowLong(hwnd,0,1^GetWindowLong(hwnd,0));
OutputDebugString(TEXT("..LBChild 1.."));
SetFocus(hwnd);
OutputDebugString(TEXT("..LBChild 2.."));
InvalidateRect(hwnd,NULL,TRUE);
return 0;


case WM_SETFOCUS: //For focus messages,invalidate the window for repaint
idFocus=GetWindowLong(hwnd,GWL_ID);
OutputDebugString(TEXT("..Child_SetFocus.."));


case WM_KILLFOCUS: //For through
InvalidateRect(hwnd,NULL,TRUE);
OutputDebugString(TEXT("..Child_KillFocus.."));
return 0;

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

GetClientRect(hwnd,&rect);
Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom);

if (GetWindowLong(hwnd,0))
{
MoveToEx(hdc,0,0,NULL);
LineTo(hdc,rect.right,rect.bottom);
MoveToEx(hdc,rect.right,rect.top,NULL);
LineTo(hdc,rect.left,rect.bottom);
}

if (hwnd==GetFocus())
{
rect.left+=rect.right/10;
rect.right-=rect.left;
rect.top+=rect.bottom/10;
rect.bottom-=rect.top;

SelectObject(hdc,GetStockObject(NULL_BRUSH));
SelectObject(hdc,CreatePen(PS_DASH,0,0));
Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom);
DeleteObject(SelectObject(hdc,GetStockObject(BLACK_PEN)));
}

EndPaint(hwnd,&ps);
return 0;
}
return DefWindowProc(hwnd,message,wParam,lParam);
}


schlafenhamster 2012-04-04
  • 打赏
  • 举报
回复
这样上次可以保留:
case WM_LBUTTONUP:
if (fBlocking)
{
fBlocking=FALSE;
//DrawBoxOutline(hWnd,ptBeg,ptEnd);
//InvalidateRect(hWnd,NULL,TRUE);
}
return 0;
case WM_PAINT:// 常规绘制
hdc=BeginPaint(hWnd,&ps);
Rectangle(hdc,ptBeg.x,ptBeg.y,ptEnd.x,ptEnd.y);
EndPaint(hWnd,&ps);
// DrawBoxOutline(hWnd,ptBeg,ptEnd);
return 0;
zwb8848happy 2012-04-04
  • 打赏
  • 举报
回复
谢谢你陪我扯了这么长时间,不胜感激!!!

可能我一开始没讲清楚,我就是用鼠标画一个矩形,释放后屏幕上有一个矩形的。。。
schlafenhamster 2012-04-04
  • 打赏
  • 举报
回复
按你的要求是“左击-》拖动-》释放”这个过程中有一个矩形框。释放后矩形框消失。
不需要处理WM_PAINT的(默认处理就可以了,所以不要响应)
zwb8848happy 2012-04-04
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 的回复:]
char Prompt[80];
sprintf(Prompt,"%d",x);
OutputDebugString(Prompt);
另外我把WM_PAINT都去了,不要的(一定要去干净)
[/Quote]

你这个不就是将一些变量值输出吗!
但我还是不明白为什么不在监视窗口中查看这些变量的值?
还有,“另外我把WM_PAINT都去了,不要的(一定要去干净)”这句话我也有点糊涂,不知道你的目的
加载更多回复(10)
API之网络函数1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接 WNetAddConnection2 创建同一个网络资源的连接 WNetAddConnection3 创建同一个网络资源的连接 WNetCancelConnection 结束一个网络连接 WNetCancelConnection2 结束一个网络连接 WNetCloseEnum 结束一次枚举操作 WNetConnectionDialog 启动一个标准对话框,以便建立同网络资源的连接 WNetDisconnectDialog 启动一个标准对话框,以便断开同网络资源的连接 WNetEnumResource 枚举网络资源 WNetGetConnection 获取本地或已连接的一个资源的网络名称 WNetGetLastError 获取网络错误的扩展错误信息 WNetGetUniversalName 获取网络中一个文件的远程名称以及/或者UNC(统一命名规范)名称 WNetGetUser 获取一个网络资源用以连接的名字 WNetOpenEnum 启动对网络资源进行枚举的过程 2. API之消息函数 BroadcastSystemMessage 将一条系统消息广播给系统中所有的顶级窗口 GetMessagePos 取得消息队列中上一条消息处理完毕时的鼠标指针屏幕位置 GetMessageTime 取得消息队列中上一条消息处理完毕时的时间 PostMessage 将一条消息投递到指定窗口的消息队列 PostThreadMessage 将一条消息投递给应用程序 RegisterWindowMessage 获取分配给一个字串标识符的消息编号 ReplyMessage 答复一个消息 SendMessage 调用一个窗口的窗口函数,将一条消息发给那个窗口 SendMessageCallback 将一条消息发给窗口 SendMessageTimeout 向窗口发送一条消息 SendNotifyMessage 向窗口发送一条消息 3. API之文件处理函数 CloseHandle 关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等 CompareFileTime 对比两个文件的时间 CopyFile 复制文件 CreateDirectory 创建一个新目录 CreateFile 打开和创建文件、管道、邮槽、通信服务、设备以及控制台 CreateFileMapping 创建一个新的文件映射对象 DeleteFile 删除指定文件 DeviceIoControl 对设备执行指定的操作 DosDateTimeToFileTime 将DOS日期和时间值转换成一个 win32 FILETIME 值 FileTimeToDosDateTime 将一个 win32 FILETIME 值转换成DOS日期和时间值 FileTimeToLocalFileTime 将一个FILETIME结构转换成本地时间 FileTimeToSystemTime 根据一个FILETIME结构的内容,装载一个SYSTEMTIME结构 FindClose 关闭由FindFirstFile函数创建的一个搜索句柄 FindFirstFile 根据文件名查找文件 FindNextFile 根据调用FindFirstFile函数时指定的一个文件名查找下一个文件 FlushFileBuffers 针对指定的文件句柄,刷新内部文件缓冲区 FlushViewOfFile 将写入文件映射缓冲区的所有数据都刷新到磁盘 GetBinaryType 判断文件是否可以执行 GetCompressedFileSize 判断一个压缩文件在磁盘上实际占据的字节数 GetCurrentDirectory 在一个缓冲区中装载当前目录 GetDiskFreeSpace 获取与一个磁盘的组织有关的信息,以及了解剩余空间的容量 GetDiskFreeSpaceEx 获取与一个磁盘的组织以及剩余空间容量有关的信息 GetDriveType 判断一个磁盘驱动器的类型 GetExpandedName 取得一个压缩文件的全名 GetFileAttributes 判断指定文件的属性 GetFileInformationByHandle 这个函数提供了获取文件信息的一种机制 GetFileSize 判断文件长度 GetFileTime 取得指定文件的时间信息 GetFileType 在给出文件句柄的前提下,判断文件类型 GetFileVersionInfo 从支持版本标记的一个模块里获取文件版本信息

16,472

社区成员

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

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

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