一个SDK来实现普通画图跟双缓冲画图区别的小程序,能运行但有问题。

yiruirui0507 2011-01-19 03:59:03
#include <windows.h>
#include "resource.h"
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
void PThanshu(HWND);//普通画图函数
void DHChanshu(HWND);//双缓冲画图函数

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName [] = TEXT ("GDI") ;
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.lpszMenuName = szAppName;
wndclass.lpszClassName = szAppName ;

if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}

hwnd = CreateWindow (szAppName, TEXT ("GDI TEST"),
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 ;
}
static int cxClient, cyClient;
static int radius=1;
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

HDC hdc;
HINSTANCE hInstance ;
static int pt,gdi;//PT--普通画图,GDI--双缓冲画图
PAINTSTRUCT ps ;
RECT rect;

TCHAR szAppName[]="GDI";

switch (message)
{
case WM_CREATE:
SetTimer(hwnd,1,1000,NULL);
hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;

return 0 ;
case WM_TIMER:
//GetClientRect(hwnd,&rect);//本打算在这里触发WM_PAINT消息的
// InvalidateRect(hwnd,&rect,TRUE);
if(radius<16)
{radius++;}
else
{radius=0;}

if(pt)
{
PThanshu(hwnd);//普通画图
}
else if(gdi)
{
DHChanshu(hwnd);//双缓冲画图
}
else
return 0;


case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;

case WM_PAINT:
/*if(pt==1)
{
hdc = BeginPaint (hwnd, &ps) ;
for(int x=0;x<cxClient;x+=16)
for(int y=0;y<cyClient;y=+16)
{
Ellipse(hdc,x,y,x+radius,y+radius);

}
EndPaint (hwnd, &ps) ;
}
else
{
hdc=BeginPaint (hwnd, &ps) ;
DrawText(hdc,szAppName,-1,&rect,DT_CENTER);
EndPaint(hwnd,&ps);

}*/
hdc=BeginPaint(hwnd,&ps);
GetClientRect(hwnd,&rect);
DrawText(hdc,szAppName,-1,&rect,DT_CENTER);
EndPaint(hwnd,&ps);

return 0 ;
case WM_COMMAND:
if(lParam==0)
{
switch(wParam)
{

case IDM_PT://普通画图菜单项ID
pt=1;
gdi=0;
return 0;
case IDM_DHC://双缓冲画图菜单项ID
gdi=1;
pt=0;
return 0;
default:
return 0;

}
}


case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
void PThanshu(HWND hwnd)
{
HDC hdc=GetDC(hwnd);
RECT rect;
GetClientRect(hwnd,&rect);

for(int x=0;x<cxClient;x+=16)
for(int y=0;y<cyClient;y=+16)
{
Ellipse(hdc,x,y,x+radius,y+radius);

}
ReleaseDC(hwnd,hdc);
}
void DHChanshu(HWND hwnd)//暂且没实现
{
MessageBox(hwnd,TEXT("zhaoxujing"),TEXT("yiruirui"),MB_OK);
}


以上是代码,能够运行,但是运行过程中我单击 普通画图的时候仅仅画了2个椭圆,然后就没了,关闭出现无响应的情况,可以结束进程给予关闭。这里什么导致的这个问题呢,麻烦大家给看看。3Q!!!
...全文
211 14 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
yiruirui0507 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 varding 的回复:]
引用 12 楼 yiruirui0507 的回复:

C/C++ code
void DHChanshu(HWND hwnd)//暂且没实现
{
//MessageBox(hwnd,TEXT("zhaoxujing"),TEXT("yiruirui"),MB_OK);
HDC hdc=GetDC(hwnd);
RECT rect;
GetClientRect(hwnd,&a……
[/Quote]

不是这里的问题,FILLRECT(HDCMEM,&RECT,NULL)就OK了,是填充内存设备内容。谢谢。
varding 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 yiruirui0507 的回复:]

C/C++ code
void DHChanshu(HWND hwnd)//暂且没实现
{
//MessageBox(hwnd,TEXT("zhaoxujing"),TEXT("yiruirui"),MB_OK);
HDC hdc=GetDC(hwnd);
RECT rect;
GetClientRect(hwnd,&rect);
cxClien……
[/Quote]
FillRect(hdc,&rect,NULL);
你的画刷是NULL,画出来就是黑的

yiruirui0507 2011-01-19
  • 打赏
  • 举报
回复
void DHChanshu(HWND hwnd)//暂且没实现
{
//MessageBox(hwnd,TEXT("zhaoxujing"),TEXT("yiruirui"),MB_OK);
HDC hdc=GetDC(hwnd);
RECT rect;
GetClientRect(hwnd,&rect);
cxClient=rect.right;
cyClient=rect.bottom;

HDC hdcmem=CreateCompatibleDC(hdc);
HBITMAP hbitmap=CreateCompatibleBitmap(hdc,cxClient,cyClient);
SelectObject(hdcmem,hbitmap);
FillRect(hdc,&rect,NULL);
for(int x=0;x<cxClient;x+=16)
for(int y=0;y<cyClient;y+=16)
{
Ellipse(hdcmem,x,y,x+radius,y+radius);

}
BitBlt(hdc,0,0,cxClient,cyClient,hdcmem,0,0,SRCCOPY);
ReleaseDC(hwnd,hdc);

}

这个函数是实现的双缓冲绘图,不晓得为什么每次都有黑色背景?很奇怪。。。
yiruirui0507 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 varding 的回复:]
引用 5 楼 yiruirui0507 的回复:

引用 3 楼 happyparrot 的回复:
for(int y=0;y<cyClient;y=+16)
应该是for(int y=0;y<cyClient;y+=16)


哦,多谢提醒啊,这里改了之后整个客户区倒是有椭圆了,但是椭圆没变大???没按想象中的那样,椭圆从小变成大。



画图前先用FillSolidRect清除背……
[/Quote]
FillSolidRect是MFC里面的,SDK中没啊???
yiruirui0507 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 varding 的回复:]
我把你的代码测试了下,你的WM_SIZE里面得到的大小有问题



C/C++ code
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;


改成这个:

C/C++ code
void PThanshu(HWND hwnd)
{……
[/Quote]
哦,多谢,你的这个的确可以,我的cxClient,cyClient都是全局变量啊,所以我认为放置在WM_SIZE中会比较准确点。没想到,这里竟然也能出问题????
varding 2011-01-19
  • 打赏
  • 举报
回复
我把你的代码测试了下,你的WM_SIZE里面得到的大小有问题

 case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;


改成这个:
void PThanshu(HWND hwnd)
{
HDC hdc=GetDC(hwnd);
RECT rect;

GetClientRect(hwnd,&rect);

cxClient = rect.right;//添加这2个就行了
cyClient = rect.bottom;
...
}

快乐鹦鹉 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 yiruirui0507 的回复:]
引用 3 楼 happyparrot 的回复:
for(int y=0;y<cyClient;y=+16)
应该是for(int y=0;y<cyClient;y+=16)


哦,多谢提醒啊,这里改了之后整个客户区倒是有椭圆了,但是椭圆没变大???没按想象中的那样,椭圆从小变成大。
[/Quote]
椭圆直径一直是1???
varding 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 yiruirui0507 的回复:]

引用 3 楼 happyparrot 的回复:
for(int y=0;y<cyClient;y=+16)
应该是for(int y=0;y<cyClient;y+=16)


哦,多谢提醒啊,这里改了之后整个客户区倒是有椭圆了,但是椭圆没变大???没按想象中的那样,椭圆从小变成大。
[/Quote]
画图前先用FillSolidRect清除背景试试
varding 2011-01-19
  • 打赏
  • 举报
回复
你这直接绘图的最好放到WM_PAINT里面,timer里InvalidRect就行了
yiruirui0507 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 happyparrot 的回复:]
for(int y=0;y<cyClient;y=+16)
应该是for(int y=0;y<cyClient;y+=16)
[/Quote]

哦,多谢提醒啊,这里改了之后整个客户区倒是有椭圆了,但是椭圆没变大???没按想象中的那样,椭圆从小变成大。
快乐鹦鹉 2011-01-19
  • 打赏
  • 举报
回复
由于你写成了y=+16,所以y的值一直不变化,导致死循环,而y只出现两个值,即y=0和y=16
快乐鹦鹉 2011-01-19
  • 打赏
  • 举报
回复
for(int y=0;y<cyClient;y=+16)
应该是for(int y=0;y<cyClient;y+=16)
yiruirui0507 2011-01-19
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 happyparrot 的回复:]
调试一下普通画图时,cxClient和cyClient的值
另外在定时器中,你怎么写if(radius<16)
{radius++;}
else
{radius=0;}

啥意思?
[/Quote]

Ellipse(hdc,x,y,x+radius,y+radius)
我不想让他画的太大,所以限制一下,然后再又从头画。
快乐鹦鹉 2011-01-19
  • 打赏
  • 举报
回复
调试一下普通画图时,cxClient和cyClient的值
另外在定时器中,你怎么写if(radius<16)
{radius++;}
else
{radius=0;}

啥意思?
private float refX; //手指移动时上一刻在X轴上的位置 private float refY; //Y private float initialX; //触摸屏幕时,按下去时的X轴上位置 private float initialY; //Y private float centerX; //画圆时圆心点X轴位置 private float centerY; //Y轴位置 private float circleRadius = 1; //半径 aaaaaa private RectF ovalRect; //用于画椭圆时的矩形类 private Point point; //用于画点的“点”类 private Rect rect; //用于画正方形/矩形的矩形类 private Point[] trianglePoints = new Point[3]; //用于画三角形时存储三角形的三个点 private Point[] points = new Point[3]; private Paint paint; //画笔 private Path path; //图像路径 private Bitmap mBitmap; //用来实现双缓冲的Bitmap private Canvas mCanvas; //用来实现双缓冲的Canvas private DisplayMetrics dm; private int drawType = DrawType.Scrawl; //画图类型 private boolean isClear = false; //onDraw方法中用来判断当前是否是清除图像 public DrawView(Context context, AttributeSet attrs) { super(context, attrs); createCanvas(); //设置画笔属性 paint = new Paint(); paint.setAntiAlias(true); paint.setColor(Color.RED); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(5); paint.setStrokeCap(Paint.Cap.ROUND); //设置笔刷圆形样式 paint.setPathEffect(new CornerPathEffect(20)); //实例“路径”对象 path = new Path(); } @Override public boolean onTouchEvent(MotionEvent event) { float currentX = event.getX(); float currentY = event.getY(); //如果是随意涂鸦 if(drawType == DrawType.Scrawl){ switch(event.getAction()){ case MotionEvent.ACTION_DOWN: //手按下屏幕的时候 paint.setPathEffect(new CornerPathEffect(20)); //设置圆滑效果 path.moveTo(currentX, currentY); //将画笔移动到此,设置路径的第一个点 refX = currentX; refY = currentY; break; case MotionEvent.ACTION_MOVE: //手指在屏幕上移动的时候 path.lineTo(currentX, currentY); //为路径添加一个点 refX = currentX; refY = currentY; break; case MotionEvent.ACTION_UP: //手指提起来的时候 mCanvas.drawPath(path, paint); paint.setPathEffect(new CornerPathEffect(0)); //画完后取消圆滑效果,否则在画矩形等图形的时候边角也会是圆角 path.reset(); //清空Path的任何直线和曲线,让它变成空,以便下次使用 break; } invalidate(); //这个方法请求View进行重绘,所以会调用onDraw方法

16,548

社区成员

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

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

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