冬天有小龙虾吃吗:关于编程

来源:百度文库 编辑:高校问答 时间:2024/04/28 22:38:51
利用API函数编写程序捕获鼠标信息,要求在窗口中某个位置单击鼠标右键时,程序保存捕获的鼠标点处的坐标,紧接着按下鼠标左键在窗口中拖动,程序会记下鼠标的运动轨迹,并以刚才右击鼠标时确定的点为中心绘制一簇射线!

#include <windows.h>
#include "resource.h"
//#include "English_Name.h"
#include <math.h>

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK NOM(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
BOOL CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM) ;

POINT PadCaret;
//平均字母的宽度(cxChar)、总的字母的高度(cyChar)
//大写字母的平均宽度(cxCaps),创建窗口的高度(cyClient)
int cxChar, cxCaps, cyChar, cyClient, cxClient;
static int iCursor = 1;
static int cxBuffer, cyBuffer, xCaret, yCaret ;

#define BUFFER(x,y) *(pBuffer + y * cxBuffer + x)
#define MAXPOINTS 1000
#define NUM 800
#define TWOPI (2 * 3.14159)

HWND hDlgSetBkColor;

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
//建立基本参数
HWND CreatPad;
WNDCLASS WND_Creat;
CHAR WND_CreatPad[] = "Creat_Super";

WND_Creat.cbClsExtra = 0;
WND_Creat.cbWndExtra = 0;

//美化界面
WND_Creat.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
WND_Creat.hCursor = LoadCursor(NULL, IDC_IBEAM);//载入鼠标
WND_Creat.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));
// WND_Creat.lpszMenuName= MAKEINTRESOURCE(IDR_MENU1);
WND_Creat.lpszMenuName = NULL ;

//函数调用
WND_Creat.hInstance = hInstance;
WND_Creat.lpfnWndProc = WndProc;
WND_Creat.lpszClassName = WND_CreatPad;

//window stlye
WND_Creat.style = CS_HREDRAW | CS_VREDRAW;

//注册出错检查
if(!RegisterClass(&WND_Creat))
{
MessageBox(NULL,TEXT("fail register"),"warn!",MB_ICONSTOP);
return 1;
}

//根据视窗类别建立一个视窗
CreatPad=CreateWindow(WND_CreatPad,
TEXT("Experiment_One"),
//WS_VSCROLL 垂直滚动条
//WS_HSCROLL 水平滚动条
WS_OVERLAPPEDWINDOW|WS_VSCROLL,
100,//X1
0,//Y1
800,//(X2-x1)
600,//(Y2-Y1)
NULL,
NULL,
hInstance,
NULL);

//caret 出现位置
//PadCaret.x=200;
//PadCaret.y=200;

//显示window

ShowWindow(CreatPad,nShowCmd);

MSG msg;

/*
while (GetMessage (&msg, NULL, 0, 0))
{
//TranslateMessage 翻译键盘
TranslateMessage (&msg) ;
//DispatchMessage 将信息发送给视窗处理
DispatchMessage (&msg) ;
}
*/
while (GetMessage (&msg, NULL, 0, 0))
{
if(NULL == hDlgSetBkColor || !IsDialogMessage(hDlgSetBkColor, &msg))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}

return msg.wParam ;

return 0;
}

/*
void DrawBezier (HDC hdc, POINT apt[])
{
PolyBezier (hdc, apt, 4) ;
MoveToEx (hdc, apt[0].x, apt[0].y, NULL) ;
LineTo (hdc, apt[1].x, apt[1].y) ;

MoveToEx (hdc, apt[2].x, apt[2].y, NULL) ;
LineTo (hdc, apt[3].x, apt[3].y) ;
}
*/

LRESULT CALLBACK WndProc(HWND hwnd, UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hdc ;
int i, x, y, iVertPos, iHorzPos, iPaintBeg, iPaintEnd ;
int f,g;
static POINT st[MAXPOINTS] ;
static int iCount ;
/*********************************************************************\
*PAINTSTRUCT这个结构体中包含了HDC代号,WM_PAINT这个消息获得后,进行
*执行需要这个。如:beginpaint = (hwnd , &(PAINTSTRUCT PS)) 然后HDC
*获得ps中的hdc
\*********************************************************************/
PAINTSTRUCT ps ;
//SCROLLINFO这个结构体包含了cbSize、fMask、nMin、nMax、nPage等几个成员
//后面就会逐一用到这五个成员
SCROLLINFO si ;
//
POINT pt;
//
RECT rc;
//用于改进的键盘消息输出,定义的ip和Cnum这两个暂时无用,编译会产生1 warning
enum CharacterTable{a, b, c, d} ;
static CharacterTable ip;
int Cnum;
//
static HINSTANCE hInstance;
//
static HMENU hMenuMain, hMenuEn, hMenuCh, hMenuShortCut, hMenu, IDR_MENU2_l ;

// static HMENU hMenu, IDR_MENU2_l,w ;
//
static UINT uCheck = MF_CHECKED;
//
POINT apt [NUM] ;
//
static TCHAR * pBuffer = NULL ;

//TextOut_1 会用到,wsprintf中想此个数组填充
TCHAR szBuffer [10] ;
//取得字体的基本信息
TEXTMETRIC tm ;
//
CHOOSECOLOR cc;
OPENFILENAME ofn;

static COLORREF crCustColors[16] ;

//
char szText_1[100] = {"一点提示!"};
char szText_2[100] = {"鼠标移动的轨迹会被记录,按'连接顶点' 会连接轨迹上的点"};

//光标出现
switch(message)
{
case WM_CREATE:
{

hInstance = ((LPCREATESTRUCT) lParam)->hInstance ;
/*********************************************************************************\
*GetDC(),ReleaseDC()和BeginPaint(),EndPaint()的区别
*利用GetDC()传回的hdc,可以在整个显示区域上绘图,但BeginPaint()传回的hdc,只在
*rect指定的矩形区域内绘图
*GetDC和ReleaseDC不使显示区域中任何可能的无效区域变成有效
\*********************************************************************************/

hdc = GetDC (hwnd) ;

GetTextMetrics (hdc, &tm) ;
//平均字母的宽度(cxChar)
cxChar = tm.tmAveCharWidth ;
//处理变宽的字符
if ( tm.tmPitchAndFamily = 1)
{
//大写和汉字为1.5倍的cxChar
cxCaps = 3 / 2 * cxChar;
}
else
{
//其它的cxCaps = cxChar
cxCaps = cxChar;
}
//文字间隔 :tm.tmExternalLeading默认为0 ,为加长文本长度和文本的美观,将其的值设置为10
tm.tmExternalLeading = 10;
cyChar = tm.tmHeight + tm.tmExternalLeading ;
//设置垂直卷动列的范围和初始位置

ReleaseDC (hwnd, hdc) ;

//建立动态菜单
hInstance = (HINSTANCE) GetWindowLong (hwnd, GWL_HINSTANCE) ;
hMenuMain = LoadMenu (hInstance, MAKEINTRESOURCE (IDR_MENU1)) ;
SetMenu (hwnd, hMenuMain) ;

return 0 ;
}

case WM_SIZE:
{
/*********************************************************************************\
*lParam参数的低字组中包含显示区域的宽度,高字组中包含显示区域的高度
*如:句子【cxClient = LOWORD (lParam)】求出了client的宽度
*系统在处理 WM_SIZE 的时候会自动返回 lParam,但是窗口必须是主窗口,子窗口是不行的
\*********************************************************************************/
cyClient = HIWORD (lParam) ;
cxClient = LOWORD (lParam) ;

/*
apt[0].x = 40 ;
apt[0].y = 160 ;

apt[1].x = 80 ;
apt[1].y = 80 ;

apt[2].x = 80 ;
apt[2].y = 240 ;

apt[3].x = 120 ;
apt[3].y = 160 ;
*/
/*开始使用SCROLLINFO这个结构体*/
//si.cbSize的长度为SCROLLINFO的长度
si.cbSize = sizeof (si) ;
//SIF_RANGE : 让si.nMin , si.nMax 成为滚动条的范围
//SIF_PAGE : 取得目前页面的大小,得到比例化的滚动条
si.fMask = SIF_RANGE | SIF_PAGE ;
//(0 ~ 46)
si.nMin = 0 ;
si.nMax = 46 ;
//显示区域内显示的文字的总行数
si.nPage = cyClient / cyChar ;
/************************************************************************************\
*SetScrollInfo为win32的滚动条函数
*SB_VERT : 为比例化的滚动条(此处用的是这个样式)
*SB_CTL : 为非比例化的滚动条
*SB_HORZ : 为比例化的滚动条,但是具有水平和垂直两条
*SIF_TRACKPOS : ????????????????????????
*(SB_###为鼠标的通知码)*
*最后一个参数为TRUE时,程序运行时滚动条出现时就为比例滚动条,即为当程序获得如鼠标拖动
*滚动块等动作信息时,滚动条不进行重新绘制。但当参数为FALSE时,程序运行时滚动条出现时
*就为非比例滚动条,但当程序获得如鼠标拖动滚动块等动作信息时,滚动条进行重新绘制,立刻
*重绘变为比例滚动条。
\************************************************************************************/
SetScrollInfo (hwnd, /*SB_HORZ or SB_CTL*/SB_VERT, &si, TRUE/*FALSE*/) ;

//
{
cxBuffer = max (1, cxClient / cxChar) ;
cyBuffer = max (1, cyClient / cyChar) ;

if (pBuffer != NULL)
free (pBuffer) ;

pBuffer = (TCHAR *) malloc (cxBuffer * cyBuffer * sizeof (TCHAR)) ;

for (y = 0 ; y < cyBuffer ; y++)
for (x = 0 ; x < cxBuffer ; x++)
BUFFER(x,y) = ' ' ;

xCaret = 0 ;
yCaret = 0 ;

if (hwnd == GetFocus ())
SetCaretPos (xCaret * cxChar, yCaret * cyChar) ;

InvalidateRect (hwnd, NULL, TRUE) ;

}

return 0 ;
/***************************************************************************************\
*以上的代码并只是获得WM_SIZE时所作的初期工作,真正的SCROLL工作细节在获得WM_VSCROLL中实现*
\***************************************************************************************/
}

case WM_VSCROLL:
{
//si.cbSize的长度为SCROLLINFO的长度
si.cbSize = sizeof (si) ;
/*******************************************************\
*SIF_RANGE : 让si.nMin , si.nMax 成为滚动条的范围
*SIF_PAGE : 取得目前页面的大小,得到比例化的滚动条
*SIF_POS : 获得滑块目前的位置
*SIL_ALL = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS
\*******************************************************/
si.fMask = SIF_ALL ;
//与SetScrollInfo基本类似,但可以使用LONG型的数值指向滚动块的位置等
GetScrollInfo (hwnd, SB_VERT, &si) ;
//将滚动块的位置放置于iVertPos中
iVertPos = si.nPos ;
/***********************************************************************\
*wParam的低字位是SB_THUMBTRACK时,wParam的高字位是使用者在拖动滚动块时
*的目前位置。该位置位于滚动条范围的最小值和最大值之间。在wParam的低字位是
*SB_THUMBPOSITION时,wParam的高字位是使用者释放鼠标后滚动块的最终位置。
\***********************************************************************/
switch (LOWORD (wParam))
{
//滚动块在顶部了,不能在进行移动了
case SB_TOP:
si.nPos = si.nMin ;
break ;
//滚动块在底部了,不能在进行移动了
case SB_BOTTOM:
si.nPos = si.nMax ;
break ;
//鼠标点击垂直滚动条的上面的箭头
case SB_LINEUP:
//每点击一次滚动块的位置下降一个单位
si.nPos -= 1 ;
break ;
//鼠标点击垂直滚动条的下面的箭头
case SB_LINEDOWN:
//每点击一次滚动块的位置上升一个单位
si.nPos += 1 ;
break ;
//点击滚当块的上部,每点击一次滚动块上升一个单位
case SB_PAGEUP:
si.nPos -= si.nPage ;
break ;
//点击滚当块的下部,每点击一次滚动块下降一个单位
case SB_PAGEDOWN:
si.nPos += si.nPage ;
break ;
//鼠标按住滚动块进行移动
case SB_THUMBTRACK:
si.nPos = si.nTrackPos ;
break ;
//其它的操作
default:
break ;
}
//滚动块目前的位置
si.fMask = SIF_POS ;
//把上面的(SB_#####)进行处理,得到结果,并将滚动块的位置显示于创建程序窗口
SetScrollInfo (hwnd, SB_VERT, &si, TRUE) ;
GetScrollInfo (hwnd, SB_VERT, &si) ;
//当滚动条被使用了,那么窗口的内容也要进行相应的更新
if (si.nPos != iVertPos)
{
/**********************************************************************\
ScrollWindow函数的原型 :
ScrollWindow(
HWND hWnd,
int XAmount,
int YAmount,
CONST RECT *lpRect,
CONST RECT *lpClipRect);
\**********************************************************************/
ScrollWindow ( hwnd, 0, cyChar * (iVertPos - si.nPos),
NULL, NULL) ;
//对窗口进行重绘
UpdateWindow (hwnd) ;
}

return 0 ;
}

case WM_RBUTTONDOWN:
{

}

case WM_LBUTTONDOWN:
{
iCount = 0 ;
InvalidateRect (hwnd, NULL, TRUE) ;

SetCaretPos(LOWORD(lParam), HIWORD(lParam));
ShowCaret(hwnd);
}

return 0 ;

case WM_LBUTTONUP:

InvalidateRect (hwnd, NULL, FALSE) ;
return 0 ;

case WM_MOUSEMOVE:

if (wParam & MK_LBUTTON && iCount < 1000)
{
st[iCount ].x = LOWORD (lParam) ;
st[iCount++].y = HIWORD (lParam) ;

hdc = GetDC (hwnd) ;
SetPixel (hdc, LOWORD (lParam), HIWORD (lParam), 0) ;
ReleaseDC (hwnd, hdc) ;
}
return 0 ;

//开始进行文本的输出
case WM_PAINT :
{

hdc = BeginPaint (hwnd, &ps) ;

si.cbSize = sizeof (si) ;
si.fMask = SIF_POS ;
GetScrollInfo (hwnd, SB_VERT, &si) ;
iVertPos = si.nPos ;

GetScrollInfo (hwnd, SB_HORZ, &si) ;
iHorzPos = si.nPos ;

//#define max(a,b) (((a) > (b)) ? (a) : (b))
//#define min(a,b) (((a) < (b)) ? (a) : (b))

iPaintBeg = max (0, iVertPos + ps.rcPaint.top / cyChar) ;
iPaintEnd = min (46,iVertPos + ps.rcPaint.bottom / cyChar) ;

//设置循环的次数
for (i = iPaintBeg ; i <= iPaintEnd ; i++)
{
x = cxChar * (1 - iHorzPos) ;
y = cyChar * (i - iVertPos) ;
//为了标记行数 将循环变量i作为计数器,并且显示
TextOut (hdc, x , y, szBuffer, wsprintf (szBuffer, TEXT ("%d"), i) );
//输出name数组中第一列英文名
//TextOut(hdc, x + 15 * cxCaps + 40 * cxChar, y, name[i].EnglishName,
// lstrlen (name[i].EnglishName)) ;
//输出name数组中第二列英文名对应的中文名
// TextOut(hdc,x + 15 * cxCaps , y, name[i].ChineseName,
// lstrlen (name[i].ChineseName)) ;

SetTextAlign (hdc, TA_LEFT | TA_TOP) ;

}

/*用于程序开始*/
TextOut(hdc, 50, 10, szText_1, strlen(szText_1));
TextOut(hdc, 50, 30, szText_2, strlen(szText_2));

//绘图的调用函数
switch(wParam)
{
case 1: //原型点
SelectObject(hdc, GetStockObject(BLACK_BRUSH));
Ellipse(hdc, 350, 100, 380, 130);
break;

case 2: //直线
MoveToEx(hdc, 200, 200, NULL);
LineTo(hdc, 500, 300);
break;

case 3: //直角矩形
SelectObject(hdc, GetStockObject(BLACK_BRUSH));
Rectangle(hdc, 200, 100, 400, 200);
break;

case 4: //圆角矩形
SelectObject(hdc, GetStockObject(BLACK_BRUSH));
RoundRect(hdc, 200, 100, 400, 200, 50, 40);
break;

case 5: //椭圆
SelectObject(hdc, GetStockObject(BLACK_BRUSH));
Ellipse(hdc, 200, 100, 400, 200);
break;

case 6: //饼形
SelectObject(hdc, GetStockObject(BLACK_BRUSH));
Pie(hdc, 200, 100, 400, 200, 450, 220, 150, 220);
break;

case 7: //圆弧
SelectObject(hdc, GetStockObject(BLACK_BRUSH));
Arc(hdc, 200, 100, 400, 200, 450, 220, 150, 220);
break;

case 8: //弦
SelectObject(hdc, GetStockObject(BLACK_BRUSH));
Chord(hdc, 200, 100, 400, 200, 450, 220, 150, 220);
break;

case 9: //SINAWAVE
{
int h;
MoveToEx (hdc, 0, 250, NULL) ;
LineTo (hdc,300, 250) ;

for (h = 0 ; h < NUM ; h++)
{
apt[h].x = h * 300 / NUM ;
apt[h].y = (int) (250 * (1 - sin (TWOPI * h / NUM))) ;
}

Polyline (hdc, apt, NUM) ;
break;
}

case 10: //LINEDEMO
{

Rectangle (hdc, 30, 60, 210, 420);

MoveToEx (hdc, 0, 0, NULL) ;
LineTo (hdc, 30, 60) ;

MoveToEx (hdc, 0, 60, NULL) ;
LineTo (hdc, 30, 0) ;

Ellipse (hdc, 30, 60, 210, 420) ;

RoundRect (hdc, 60, 120, 180, 360, 60, 120) ;

break;
}

case 11:
{

SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
// ShowCursor (TRUE) ;

for (f = 0 ; f < iCount - 1 ; f++)
for (g = f + 1 ; g < iCount ; g++)
{
MoveToEx (hdc, st[f].x, st[f].y, NULL) ;
LineTo (hdc, st[g].x, st[g].y) ;
}

// ShowCursor (FALSE) ;
// SetCursor (LoadCursor (NULL, IDC_ARROW)) ;

// DrawBezier (hdc, apt) ;
break;
}

case 12 :
{
TextOut(hdc, 100, 50, "a", 1);
break;
}

case 13 :
{
TextOut(hdc, 120, 50, "b", 1);
break;
}

case 14 :
{
TextOut(hdc, 140, 50, "1", 1);
break;
}

}

EndPaint (hwnd, &ps) ;
return 0 ;
}

case WM_SETFOCUS :
{
//CreateCaret(,HBITMAP,,)---->WINGDIAPI HBITMAP WINAPI CreateBitmap\
//(int, int, UINT, UINT, CONST VOID *);
/*
CreateCaret(hwnd,NULL,10,20);
ShowCaret(hwnd);
*/

CreateCaret (hwnd, NULL, cxChar, cyChar) ;
SetCaretPos (xCaret * cxChar, yCaret * cyChar) ;
ShowCaret (hwnd) ;
return 0 ;

return 0;
}

case WM_KILLFOCUS :
{
//光标失去
DestroyCaret();
return 0;
}

case WM_DESTROY :
{
//程序进程的销毁
PostQuitMessage(0);
return 0;
}

// switch (LOWORD (wParam))
// {
// case ID_MENUITEM40041:
// SetClassLong(hwnd, GCL_HCURSOR, (LONG)LoadCursor
// (NULL, MAKEINTRESOURCE(32512+(iCursor++)%5)));
// return 0;
// }