帮我写个画图程序,用win32 API,实现画圆,画矩形等,用到控件 ,鼠标消息处理等。

 我来答
W825758238
2011-05-30
知道答主
回答量:20
采纳率:0%
帮助的人:13.1万
展开全部
呵呵,哥们,我们也刚学完这些,以下代码给你,要的基本符合,不过你得要在加2个资源(在insert的resource中)“鼠标的(cursor)和菜单栏的(menu)”,不加是不行的,加了后该修改的你能看的懂的,实在不行,我就直接发文件给你:

#include <windows.h>
#include "resource.h"
#include <string.h>
#include <stdio.h>
#include <math.h>
HINSTANCE g_hInstance;
int g_nToolID = 0;
struct tagLine
{
POINT ptB;
POINT ptE;
bool bIsDelete;
};
tagLine g_AllLines[100];//直线数组
int g_nLineNumber = 0; //实际直线数
struct tagCircle
{
POINT ptCenter;
int nRadius;
bool bIsDelete;
};
tagCircle g_AllCircles[100];//整圆数组
int g_nCircleNumber = 0; // 实际保存的圆个数

POINT pt1 = {200,200};
POINT pt2 = {200,200};
POINT pt3 = {0,0};
int g_nState = 0;
//功能:画一线直线段
void DrawLine(HDC hDC,POINT ptB,POINT ptE)
{
::MoveToEx(hDC,ptB.x,ptB.y,NULL);
::LineTo(hDC,ptE.x,ptE.y);
}
//功能:已知两点求距离
int Distance(POINT pt1,POINT pt2)
{
int nR = 0;
nR=sqrt((pt1.x - pt2.x)*(pt1.x - pt2.x) +(pt1.y - pt2.y)*(pt1.y- pt2.y));
return nR;
}

void DrawCircle(HDC hDC,POINT ptC,int nR)
{

::Ellipse(hDC,ptC.x - nR,ptC.y - nR,ptC.x + nR,ptC.y + nR);
}

void OnMouseMove(POINT ptPos,HWND hWnd)
{
if(g_nToolID == ID_CIRCLE)
{
if(g_nState == 1)
{
HDC hDC = ::GetDC(hWnd);
//取得系统预定义一个“空心刷子”
HBRUSH hBrush = (HBRUSH)::GetStockObject(NULL_BRUSH);
::SelectObject(hDC,hBrush);

::SetROP2(hDC,R2_NOTXORPEN);

DrawLine(hDC,pt1,pt2);
int nR = Distance(pt1,pt2);
DrawCircle(hDC,pt1,nR);

pt3 = ptPos;
nR = Distance(pt1,pt3);
DrawCircle(hDC,pt1,nR);
DrawLine(hDC,pt1,pt3);

pt2 = pt3;

::ReleaseDC(hWnd,hDC);
}
}else if(g_nToolID == ID_LINE)
{
if(g_nState == 1)
{
HDC hDC = ::GetDC(hWnd);
pt3=ptPos;
//用背景色,绘制上一次的位置==>擦除
::SetROP2(hDC,R2_NOTXORPEN);
::DrawLine(hDC,pt1,pt2);
::DrawLine(hDC,pt1,pt3);
pt2 = pt3;
::ReleaseDC(hWnd,hDC);
}
}
}

void OnLButtonUp(POINT ptPos)
{

if(g_nToolID == ID_CIRCLE)
{
if(g_nState == 1)
{
tagCircle aCir;
aCir.ptCenter = pt1;
aCir.nRadius = Distance(pt1,ptPos);
aCir.bIsDelete = false;

g_AllCircles[g_nCircleNumber] = aCir;
g_nCircleNumber = g_nCircleNumber + 1;
g_nState = 0;
}

}else if(g_nToolID == ID_LINE)
{
if(g_nState == 1)
{
g_nState = 0;
tagLine aLine;
aLine.ptB = pt1;
aLine.ptE = pt3;
aLine.bIsDelete = false;
g_AllLines[g_nLineNumber] = aLine;
g_nLineNumber = g_nLineNumber + 1;
}
}

}

//功能:判断点是否在直线段上
bool PtOnCircle(POINT pt,POINT ptC,int nR)
{
int nL = Distance(pt,ptC);
if( fabs(nL - nR) < 5 )
{
return true;
}else
{
return false;
}
}

//功能:判断点是否在直线段上
bool PtOnLine(POINT pt,POINT ptB,POINT ptE)
{
int nL1 = Distance(pt,ptB);
int nL2 = Distance(pt,ptE);
int nL3 = Distance(ptB,ptE);
if( fabs(( nL1 + nL2 ) - nL3) < 5 )
{
return true;
}else
{
return false;
}
}
void OnLButtonDown(HWND hWnd,POINT ptPos)
{
if(g_nToolID == ID_CIRCLE)
{
if(g_nState == 0)
{
g_nState = 1;
pt2 = pt1 = ptPos;
}
}else if(g_nToolID == ID_LINE)
{
if(g_nState == 0)
{
g_nState = 1;
pt2 = pt1 = ptPos;
}
}else if(g_nToolID == ID_DELETE)
{
//判断当前鼠标点是否在某一个直线段上
for(int nI = 0; nI < g_nLineNumber; nI = nI + 1)
{
tagLine* pLine = &g_AllLines[nI];

if(PtOnLine(ptPos,(*pLine).ptB,(*pLine).ptE))
{
char cTxt[100];
sprintf(cTxt,"nI = %d\n",nI);
::OutputDebugString(cTxt);
(*pLine).bIsDelete = true;
break;
}
}
//判断当前鼠标点是否在某一个圆上
for(nI = 0; nI < g_nCircleNumber; nI = nI + 1)
{
tagCircle* pCircle = &g_AllCircles[nI];

if(PtOnCircle(ptPos,(*pCircle).ptCenter,(*pCircle).nRadius))
{
(*pCircle).bIsDelete = true;
break;
}
}

::InvalidateRect(hWnd,NULL,TRUE);
}

}
void OnPaint(HDC hDC)
{
// 1.重绘圆
//取得系统预定义一个“空心刷子”
HBRUSH hBrush = (HBRUSH)::GetStockObject(NULL_BRUSH);
::SelectObject(hDC,hBrush);

for(int nI = 0; nI < g_nCircleNumber; nI++)
{
tagCircle aCir;
aCir = g_AllCircles[nI];
if(aCir.bIsDelete == false)
{
DrawCircle(hDC,aCir.ptCenter,aCir.nRadius);
}
}
// 2.重绘直线段
for(nI = 0; nI < g_nLineNumber; nI = nI + 1)
{
tagLine aLine = g_AllLines[nI];
if(aLine.bIsDelete == false)
{
::DrawLine(hDC,aLine.ptB,aLine.ptE);
}
}
}

void OnCommand(HWND hWnd,int nCmdID)
{
switch(nCmdID)
{
case ID_EXIT:
::DestroyWindow(hWnd);
break;
case ID_LINE:
g_nToolID = ID_LINE;
break;
case ID_CIRCLE:
g_nToolID = ID_CIRCLE;
break;
case ID_DELETE:
g_nToolID = ID_DELETE;
break;
}
}

// 窗口回调函数
int WndProc(HWND hWnd,
int message,
int wParam,
int lParam)
{
switch (message)
{
case WM_SETCURSOR:
{
HCURSOR hCur1 = ::LoadCursor(g_hInstance,"pen_cursor");
HCURSOR hCur2 = ::LoadCursor(g_hInstance,"hand_cursor");
HCURSOR hCur3 = ::LoadCursor(g_hInstance,"point_cursor");
HCURSOR hCur4 = ::LoadCursor(g_hInstance,"arrow_cursor");

switch(g_nToolID)
{
case ID_LINE:
::SetCursor(hCur1);
break;
case ID_CIRCLE:
::SetCursor(hCur2);
break;
case ID_DELETE:
::SetCursor(hCur3);
break;
default:
::SetCursor(hCur1);
}

break;
}
case WM_COMMAND:
{
int nID = LOWORD(wParam);
OnCommand(hWnd,nID);
break;
}
case WM_LBUTTONDOWN:
{
POINT ptPos;
ptPos.x = LOWORD(lParam);
ptPos.y = HIWORD(lParam);
OnLButtonDown(hWnd,ptPos);
}
break;
case WM_LBUTTONUP:
{
POINT ptPos;
ptPos.x = LOWORD(lParam);
ptPos.y = HIWORD(lParam);
OnLButtonUp(ptPos);
}
break;
case WM_MOUSEMOVE:
{
POINT ptPos;
ptPos.x = LOWORD(lParam);
ptPos.y = HIWORD(lParam);
OnMouseMove(ptPos,hWnd);
}
break;

case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hDC = ::BeginPaint(hWnd,&ps);
OnPaint(hDC);
::EndPaint(hWnd,&ps);
break;
}

case WM_DESTROY: //窗口关闭时发送
::PostQuitMessage(0); //在消息队列的尾部添加一个0消息,以示,结束程序
break;
default:
return ::DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

int WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
char* lpCmdLine,
int nCmdShow)
{
g_hInstance = hInstance;

WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = "menu1";
wcex.lpszClassName = "ABCDE";
wcex.hIconSm = NULL;
RegisterClassEx(&wcex);

HWND hWnd = CreateWindow("ABCDE",
"WanJie",
WS_OVERLAPPEDWINDOW,
50, 50, //(x,y)
500, 500, // (w,h)
NULL,
NULL,
hInstance,
NULL);

ShowWindow(hWnd,SW_SHOW);

MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
DispatchMessage(&msg);
}

return 1;
}
追问
为什么要定义直线数组阿,我们老师用的捕获鼠标的按下、拖动和松开消息来决定所画的直线矩形的,如何载入一个位图,在.rc文件中定义位图资源,如何定义菜单资源,捕获的command消息时如何区分的,用wParam区分消息吗?
追答
数组是专门来存储线和圆。
是的,是那样,LBUTTONDOWN就是点击鼠标左键(你所说的鼠标按下),MOUSEMOVE是鼠标托动,LBUTTONUP就是松开,这样绘出图形。
位图不难,可以导入,也可自己画,你们应该没学,学了就会了,菜单也差不多。。现在我这在学控件

参考资料: L

ucbjcxk
2011-05-19 · TA获得超过352个赞
知道答主
回答量:395
采纳率:0%
帮助的人:182万
展开全部
Dim x1 As Single, y1 As Single, s As Integer
Const pi = 3.14159265
Private Sub Form_Load()
Command1.Caption = "圆"
Command2.Caption = "矩形"
Command3.Caption = "三角"
Command4.Caption = "五角"
Command5.Caption = "清"
End Sub
Private Sub Command1_Click()
s = 1
End Sub

Private Sub Command2_Click()
s = 2
End Sub

Private Sub Command3_Click()
s = 3
End Sub

Private Sub Command4_Click()
s = 4
End Sub

Private Sub Command5_Click()
Picture1.Cls
End Sub
Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
If Button = 1 Then x1 = x: y1 = y
End Sub
Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, x As Single, y As Single)
If Button = 1 Then
Picture1.AutoRedraw = False
Picture1.Refresh
Picture1.PSet (x1, y1)
Select Case s
Case 1
Picture1.Circle (x1, y1), Sqr((x - x1) ^ 2 + (y - y1) ^ 2)
Case 2
Picture1.Line (x1, y1)-(x, y), , B
Case 3
duobianxing x1, y1, x, y, 3, 60
Case 4
duobianxing x1, y1, x, y, 5, 36
End Select
End If
End Sub
Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
If Button = 1 Then
Picture1.AutoRedraw = True
Select Case s
Case 1
Picture1.Circle (x1, y1), Sqr((x - x1) ^ 2 + (y - y1) ^ 2)
Case 2
Picture1.Line (x1, y1)-(x, y), , B
Case 3
duobianxing x1, y1, x, y, 3, 60
Case 4
duobianxing x1, y1, x, y, 5, 36
End Select
End If
End Sub
'duobianxing函数参数:
'zhongxinX-多边形中心的横坐标
'zhongxinY-多边形中心的纵坐标
'dingdianX-多边形一个顶点的横坐标
'dingdianY-多边形一个顶点的纵坐标
'bianhuoxing-正多边形的边数或者星形的星角数,例如biaohuoxing=5,dingjiao=72则为正五边形,若dingjiao=36则为五角星(该函数将正多边形按相邻顶角点间的折点成直线的特殊星形绘制)
'dingjiao-多边形的顶角的角度(角度制°)
Function duobianxing(ByVal zhongxinX As Single, ByVal zhongxinY As Single, ByVal dingdianX As Single, ByVal dingdianY As Single, ByVal bianhuoxing As Integer, ByVal dingjiao As Single)
If bianhuoxing = 0 Then Exit Function
l = Sqr((zhongxinX - dingdianX) ^ 2 + (zhongxinY - dingdianY) ^ 2) '星形中心到顶角距离
t1 = Abs(Tan((dingjiao / 2) * pi / 180)) '星形顶角的1/2求正切
t2 = Abs(Tan((360 / (2 * bianhuoxing)) * pi / 180)) '星形每条边所对应的中心角的1/2求正切
r = l * t2 / (t1 + t2) / Cos((dingjiao / 2) * pi / 180) '星形边长
If zhongxinX = dingdianX Then '求星形中心到顶角这条线的角度j
j = IIf(dingdianY < zhongxinY, 90, -90)
Else
j = Atn((zhongxinY - dingdianY) / (dingdianX - zhongxinX)) * 180 / pi
If dingdianX < zhongxinX Then
If dingdianY > zhongxinY Then
j = j - 180
Else
j = j + 180
End If
End If
End If
j1 = j - dingjiao / 2 '边偏离初始角1
j2 = 360 / bianhuoxing + dingjiao + j - dingjiao / 2 '边偏离初始角2(如果是正多边形j1=j2)
px1 = dingdianX: py1 = dingdianY '指定星形的第一个顶点
For i = 1 To bianhuoxing * 2
If i Mod 2 = 0 Then
px2 = px1 + r * Cos(j2 * pi / 180): py2 = py1 - r * Sin(j2 * pi / 180) '指定星形下一个顶点
j2 = j2 + 360 / bianhuoxing '边偏角+2个边长对应的中心角
Else
px2 = px1 - r * Cos(j1 * pi / 180): py2 = py1 + r * Sin(j1 * pi / 180)
j1 = j1 + 360 / bianhuoxing
End If
Picture1.Line (px1, py1)-(px2, py2) '画线
px1 = px2: py1 = py2
Next
End Function
追问
这是什么写的,我看不懂,我们老师要写思路的。用那个用到WinMain,WndProc的语言(API)写。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
敛正雅7f
2011-05-18 · TA获得超过2030个赞
知道大有可为答主
回答量:1553
采纳率:0%
帮助的人:1740万
展开全部
用MFC可以吧?
追问
不行,用API, 用vc开发。实现画点,矩形,直线,圆角矩形,椭圆,饼图,画刷改变等,并能载入一幅bmp位图。
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 1条折叠回答
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式