请问画图里边的画笔是如何实现的呢?

wengzhong 2004-05-06 10:39:06
比如WINDOWS或者FLASHMX之类的作图软件里边的画笔.
是怎么做到很快的采样,来跟踪鼠标的轨迹的呢?
我发现我的采样很慢,移动一快就出现断点了!
我现在是这么做的!




case WM_LBUTTONDOWN:
xPos=LOWORD(lParam);
yPos=HIWORD(lParam);


bLeftButtonDown=true;
if(bFill==true)
{
bScreen[xPos][yPos]=false;
Fill(xPos,yPos);
bFill=false;
InvalidateRect(hwnd,NULL,TRUE);
}
else
{
bScreen[xPos][yPos]=true;
rect.left=xPos;
rect.right=xPos+1;
rect.bottom=yPos+1;
rect.top=yPos;
InvalidateRect(hwnd,&rect,TRUE);
}



return 0;
case WM_LBUTTONUP:
bLeftButtonDown=false;
return 0;
case WM_MOUSEMOVE:
xPos=LOWORD(lParam);
yPos=HIWORD(lParam);
if(bLeftButtonDown==true)
{
bScreen[xPos][yPos]=true;
rect.left=xPos;
rect.right=xPos+1;
rect.bottom=yPos+1;
rect.top=yPos;
InvalidateRect(hwnd,&rect,TRUE);
}
return 0;
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
for(i=ps.rcPaint.left;i<ps.rcPaint.right+1;++i)
for(j=ps.rcPaint.top;j<ps.rcPaint.bottom+1;++j)
if(bScreen[i][j]==true)
SetPixel(hdc,i,j,RGB(0,0,0));


EndPaint(hwnd,&ps);
return 0;
case WM_COMMAND:
bFill=true;
return 0;
...全文
161 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
wengzhong 2004-05-06
  • 打赏
  • 举报
回复
还是先解释一下我想做什么我吧:)
我们最近在上图形学,然后一个作业是填充多边形.
然后我就想模拟做一个画图那样的程序,画出来一个图,然后可以填充的.
我得保存所有的点的信息,然后进行填充.我想画图软件也应该是自己保存所有的点信息的吧!
我的填充的程序如下!
无法画出来一个连续的线
如果使用LineTo画出来的线连续但是就不那么光滑了.不知道该怎么办了!
所以很想知道WINDOWS画图程序是怎么做的画笔,他的那个又快,又连续,还光滑:)
使用的是VC++6.0
里边的bool可以通过编译!


#include <windows.h>
#include <stdio.h>






LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
void Fill(int x,int y);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static char szAppName[] = "多边形的填充" ;
HWND hwnd ;
MSG msg ;
WNDCLASSEX wndclass ;

wndclass.cbSize = sizeof (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 = NULL ;
wndclass.lpszClassName = szAppName ;
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ;

RegisterClassEx (&wndclass) ;

hwnd = CreateWindow (szAppName, "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 ;
}
bool bScreen[1025][768];

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int cxClient,cyClient;
int xPos,yPos;
int i,j;
static bool bLeftButtonDown;
static bool bFill;
static HWND hbutton;
RECT rect;
HDC hdc;
PAINTSTRUCT ps;
HINSTANCE hInstance;

switch(message)
{
case WM_CREATE:

for(i=0;i<1025;++i)
for(j=0;j<769;++j)
bScreen[i][j]=false;
bLeftButtonDown=false;
hInstance=(HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE);
hbutton=CreateWindow(TEXT("button"),TEXT("填充"),WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
0,0,100,30,,hwnd,(HMENU)0,hInstance,NULL);
bFill=false;
return 0;
case WM_SIZE:
cxClient=HIWORD(lParam);
cyClient=LOWORD(lParam);
return 0;
case WM_LBUTTONDOWN:
xPos=LOWORD(lParam);
yPos=HIWORD(lParam);
bLeftButtonDown=true;
if(bFill==true)
{
bScreen[xPos][yPos]=false;
Fill(xPos,yPos);
bFill=false;
InvalidateRect(hwnd,NULL,TRUE);
}
else
{
bScreen[xPos][yPos]=true;
rect.left=xPos;
rect.right=xPos+1;
rect.bottom=yPos+1;
rect.top=yPos;
InvalidateRect(hwnd,&rect,TRUE);
}
return 0;
case WM_LBUTTONUP:
bLeftButtonDown=false;
return 0;
case WM_MOUSEMOVE:
xPos=LOWORD(lParam);
yPos=HIWORD(lParam);
if(bLeftButtonDown==true)
{
bScreen[xPos][yPos]=true;
rect.left=xPos;
rect.right=xPos+1;
rect.bottom=yPos+1;
rect.top=yPos;
InvalidateRect(hwnd,&rect,TRUE);
}
return 0;
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
for(i=ps.rcPaint.left;i<ps.rcPaint.right+1;++i)
for(j=ps.rcPaint.top;j<ps.rcPaint.bottom+1;++j)
if(bScreen[i][j]==true)
SetPixel(hdc,i,j,RGB(0,0,0));


EndPaint(hwnd,&ps);
return 0;
case WM_COMMAND:
bFill=true;
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,message,wParam,lParam);
}
void Fill(int x,int y)
{
if(x>=0&&x<1025&&y>=0&&y<769&&bScreen[x][y]==false)
{
bScreen[x][y]=true;
Fill(x-1,y);
Fill(x,y-1);
Fill(x,y+1);
Fill(x+1,y);
}
}










bluebohe 2004-05-06
  • 打赏
  • 举报
回复
SetPixel(hdc,i,j,RGB(0,0,0));
错就错在这句话,你应该使用LineTo的方式就好了
lambochan 2004-05-06
  • 打赏
  • 举报
回复
慢啊?看这段简单代码.
==============================================
void CMyView::OnMouseMove(UINT nFlags, CPoint point)
{
if(nFlags & WM_LBUTTONDOWN)//判断鼠标移动同时是否左键压下
{
CDC *pDC = GetDC();
pDC->SetPixel(point,RGB(0,0,0);//画一个点
ReleaseDC(pDC);
}
CView::OnMouseMove(nFlags, point);
}
============================================
实际上不停地拖动鼠标且左键压下,就快速画出一条...线.
wengzhong 2004-05-06
  • 打赏
  • 举报
回复
不行呀,
楼上的两位,我就是那么做的,可是对数组进行赋值很慢,不知道还能怎么优化吗?
还是方法不对?
CPEN类的实现方法在哪里能看到呢?
lambochan 2004-05-06
  • 打赏
  • 举报
回复
case WM_MOUSEMOVE & WM_LBUTTONDOWN :
xxxxxxxxxxxxxx;

是否这样?kakaka,偶用MFC,所以猜的,huhuhu~~
lambochan 2004-05-06
  • 打赏
  • 举报
回复
判断mousemove时是否鼠标左键压下了,如是,画~~~
countryboy 2004-05-06
  • 打赏
  • 举报
回复
一条直线由无数个点来填充~~!!!
countryboy 2004-05-06
  • 打赏
  • 举报
回复
知道线的轨迹,用SetPixel来画,不用手动点鼠标~!!!相当于用SetPixel点来填充直线~~!!
不过2点间的距离足够的小就看不出间断了~~!!
easyelic 2004-05-06
  • 打赏
  • 举报
回复
如果要画多N型的话,画N-1个三角形就可以了吧

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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