首页 > 代码库 > C++windows内核编程笔记day07_day08,可视化建菜单、加速键使用、绘图等
C++windows内核编程笔记day07_day08,可视化建菜单、加速键使用、绘图等
方法1:注册时指定菜单
wce.lpszMenuName=MAKEINTRESOURCE(IDR_MENUMAIN);//数字形式的资源ID转换为字符串形式的资源
方法2:
//创建窗口时加载菜单资源
HMENU menumain= LoadMenu(g_hinstance,MAKEINTRESOURCE(IDR_MENUMAIN));
menumain 传入 CreateWindowEx();//倒数第三个参数
窗口指定小图标:
1、注册时指定
wce.hIconSm=LoadIcon(g_hinstance,MAKEINTRESOURCE(IDI_ICON1));
2、调用发消息函数,修改图标
SendMessage(
(HWND) hWnd, // handle to destination window
WM_SETICON,
(WPARAM) wParam, // icontype(ICON_BIG/ICON_SMALL)
(LPARAM) lParam // LoadIcon()的返回值
);
画ICON图片到窗口:
HICON ico=LoadIcon(g_hinstance,MAKEINTRESOURCE(IDI_ICON1));
DrawIcon(hdc,100,100,ico);
修改光标:
1、wce.hCursor=LoadCursor(g_hinstance,MAKEINTRESOURCE(IDC_CUR_ARROW));//静态光标
2、动态设置光标
在鼠标移动中,会产生mousemove和WM_SETSURSOR。
case WM_SETCURSOR:
OnSetCursor(hwnd,wparam,lparam);
break;
//返回值,旧的光标:
HCURSOR SetCursor( HCURSOR hCursor // handle to cursor
);
void OnSetCursor(HWND hwnd,WPARAM wparam,LPARAM lparam)
{//HCURSOR最好作为全局变量,资源只调用一次,wm_create中
UINT hit=LOWORD(lparam);
HCURSOR c1=NULL;
if(hit==HTCLIENT)//光标在客户区
{
POINT pt={0};
RECT rc={0};
GetCursorPos(&pt);
GetClientRect(hwnd,&rc);
/*
char txt[200]={0};
ScreenToClient(hwnd,&pt);
sprintf(txt,"%d,%d ; %d,%d,%d,%d\n",pt.x,pt.y,rc.top,rc.left,rc.right,rc.bottom);
WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL);
*/
if(pt.x>=rc.right/2)//客户区域前半部分与后半部分鼠标图标设置为不同
{
//c1=LoadCursor(g_hinstance,MAKEINTRESOURCE(IDC_CUR_INPUT));
c1=LoadCursorFromFile("beam_rm.cur");//从文件加载
//c1=LoadCursorFromFile("aero_working.ani");//动态光标
}
else
{
c1=LoadCursor(g_hinstance,MAKEINTRESOURCE(IDC_CUR_ARROW));
}
}
else
{
c1=LoadCursor(g_hinstance,MAKEINTRESOURCE(IDC_CUR_ARROW));
}
if(c1!=NULL) SetCursor(c1);
}
//成功返回字符长度,失败返回0
int LoadString( HINSTANCE hInstance,
UINT uID, // resource identifier
LPTSTR lpBuffer, // 接收的字符串
int nBufferMax // 允许的最大长度
);
//读取字符串资源表中的字符
char title[30]={0};
LoadString(g_hinstance,IDS_WND,title,sizeof(title));
程序版本资源:
插入"version"资源,然后修改里面的信息就行了。
加速键(程序中的快捷键)
HACCEL LoadAccelerators( HINSTANCE hInstance,
LPCTSTR lpTableName // accelerator table name
);
int TranslateAccelerator( HWND hWnd,
HACCEL hAccTable, // handle to accelerator table
LPMSG lpMsg // message information
);
//使用,把加速键转化为点击事件,加速键的ID和按钮ID相同,就绑定在一起(执行同一个case中的事件)。
MSG msg={0};
HACCEL acc= LoadAccelerators( g_hinstance,MAKEINTRESOURCE(IDR_ACCELERATOR1));
while(GetMessage(&msg,NULL,0,0)){
if(!TranslateAccelerator(msg.hwnd,acc,&msg))//不是加速键
{
TranslateMessage(&msg);//翻译消息
DispatchMessage(&msg);//派发给 WinProc 处理消息
}
}
菜单的热键:
在后面加如:(&F),那么按alt+F就能达到和点击一样的效果。
//绘图相关,画各种基本图形
void OnPaint(HWND hwnd)
{
PAINTSTRUCT ps={0};
HDC hdc=BeginPaint(hwnd,&ps);
HICON ico=LoadIcon(g_hinstance,MAKEINTRESOURCE(IDI_ICON1));
switch(g_id)
{
//SetPixel(hdc,100,100,RGB(0,0,255));//画点
case ID_drawline://画线
MoveToEx(hdc,100,100,NULL);
LineTo(hdc,100,150);
LineTo(hdc,150,150);
break;
case ID_drawellipse://画圆
Ellipse(hdc,100,100,200,200);
RoundRect(hdc,300,100,500,300,200,200);
break;
case ID_drawrect://画距形
Rectangle(hdc,100,100,200,200);
RoundRect(hdc,300,100,500,300,0,0);
break;
case ID_drawarc://画弧形
SetArcDirection(hdc,AD_CLOCKWISE);//AD_CLOCKWISE/AD_COUNTERCLOCKWISE 顺时针或逆时针
Arc(hdc,100,100,300,300,100,100,300,300);
break;
case ID_drawwithpen://使用画笔
drawwithpen(hdc);
break;
}
EndPaint(hwnd,&ps);
}
创建画笔:
HPEN CreatePen( int fnPenStyle,// pen style
int nWidth,// pen width
COLORREF crColor // pen color
);
//把画笔设置到绘图对象,返回默认的画笔,先设置,使用完后,再设置回原来的
HGDIOBJ SelectObject( HDC hdc, // handle to DC
HGDIOBJ hgdiobj // handle to object
);
//删除画笔对象
BOOL DeleteObject( HGDIOBJ hObject // handle to graphic object
);
//使用画笔流程示例代码:
HPEN pen=CreatePen(PS_DOT,1,RGB(0,255,0));
HGDIOBJ oldpen= SelectObject(hdc,pen);
//画图操作
SelectObject(hdc,oldpen);
DeleteObject(pen);
//画刷的作用,填充封闭图形的空白部分.
//创建实心画刷-单颜色
HBRUSH CreateSolidBrush( COLORREF crColor // brush color value
);
//创建阴影画刷-阴影线
HBRUSH CreateHatchBrush( int fnStyle, // hatch style
COLORREF clrref // foreground color
);
//创建位图画刷,填充图片
HBRUSH CreatePatternBrush( HBITMAP hbmp // handle to bitmap);
其使用方法与CreatePen一样。
//获取系统GDI对象,用后不需要删除
HGDIOBJ GetStockObject(int fnObject // stock object type
);
如:HGDIOBJ brush=GetStockObject(NULL_BRUSH);//透明画刷
day71 am over
//位图相关
光栅图形-记录图像中每一点的颜色等信息
矢量图形-高妙图像算法/绘图指令等信息
位图在窗口中成像:BitBlt(…);
缩放成像:StretchBlt(……);
void drawbitmap(HDC hdc)
{
HBITMAP bitmap=LoadBitmap(g_hinstance,MAKEINTRESOURCE(IDB_BITMAP2));
HDC memdc=CreateCompatibleDC(hdc);//内存DC
HGDIOBJ oldbmp= SelectObject(memdc,bitmap);//送位图到内存dc
//MoveToEx(memdc,100,100,NULL);
//LineTo(memdc,130,150);
BITMAP bm={0};//位图信息
GetObject(bitmap,sizeof(bm),&bm);//获取位图信息。
BitBlt(hdc,0,0,bm.bmWidth,bm.bmHeight,memdc,0,0,SRCCOPY);//在窗口中成像(显示)
StretchBlt(hdc,100,300,69,51,memdc,0,0,138,102,SRCCOPY);//缩小显示
StretchBlt(hdc,100,400,276,204,memdc,0,0,138,102,SRCCOPY);//放大显示
//NOTSRCCOPY 反色/SRCCOPY 原图颜色
SelectObject(memdc,oldbmp);//还原默认
DeleteObject(bitmap);//删除位图
DeleteObject(memdc);//删除内存dc
}
坐标系:分为设备坐标系和逻辑坐标系。
在GDI绘图中,使用的是逻辑坐标系;逻辑坐标系与设备坐标系有个转换关系,可以设置。
//设置映射模式(逻辑单位与设备单位之间的关系)
int SetMapMode( HDC hdc, // handle to device context
int fnMapMode // new mapping mode
);
fnMapMode:
MM_TEXT (默认)1逻辑=1px(像素) ---坐标:x右为正,y下为正
MM_TWIPS 一般为打印机:1逻辑=1/1440英寸 ---x右为正。y上为正(下面4种模式也是这种)
MM_HIENGLISH
MM_LOENGLISH
MM_HIMETRIC
MM_LOMETRIC
MM_ISOTROPIC 自定义模式 1个逻辑=自定义
MM_ANISOTROPIC 自定义模式 X轴1个逻辑=自定义1,y轴1个逻辑=自定义2
//自定义模式时,设置逻辑与设备的比例,下面两个函数同时使用
BOOL SetWindowExtEx( HDC hdc,
int nXExtent, //逻辑的X比例
int nYExtent, //逻辑的Y比例
LPSIZE lpSize //旧的比例
);
BOOL SetViewportExtEx( HDC hdc,
int nXExtent, //设备的X比例
int nYExtent, //设备的Y比例
LPSIZE lpSize //旧的比例
);
//使用步骤
int oldmm=SetMapMode(hdc,MM_TWIPS);
//……绘图操作……
SetMapMode(hdc,oldmm);
//画字符串,比TextOut强大
int DrawText( HDC hDC, // handle to DC
LPCTSTR lpString, // text to draw int nCount, // text length
LPRECT lpRect, // formatting dimensions
UINT uFormat // text-drawing options
);
uFormat 常用选项:
DT_LEFT|DT_TOP|DT_WORDBREAK|DT_NOCLIP|DT_NOPREFIX
或DT_SINGLELINE|DT_VCENTER|DT_BOTTOM|DT_NOPREFIX|……
//TextOut 加强版,一般不用。
BOOL ExtTextOut( HDC hdc, // handle to DC
int X, // x-coordinate of reference point
int Y, // y-coordinate of reference point
UINT fuOptions, // 可为0
CONST RECT* lprc, // 可为NULL
LPCTSTR lpString, // 字符串
UINT cbCount, // 字符串长度
CONST INT* lpDx // 字符间距数组(汉字按两个字符算,之间间距用0代替)
);
步骤:
新建win32 Application工程,再新建“资源脚本”文件。
建好后,插入“资源”-“菜单”-“新建”:
建好的菜单,和加速键,如图:
保存后,包含头文件 :resource.h
//主要CPP文件代码:
// win32app.cpp : Defines the entry point for the application. // #include "stdafx.h" #include "resource.h" #include <stdio.h> HINSTANCE g_hinstance=0;//全局句柄 HMENU menu1=0,menu2=0; HANDLE g_houtput=0; void OnCreate(HWND hwnd,LPARAM lparam) { } LRESULT CALLBACK OnInitMunuPopUp( HWND hwnd, // handle to window UINT uMsg, // WM_INITMENUPOPUP WPARAM wParam, // handle to menu (HMENU) LPARAM lParam // item position and indicator ) { unsigned int index=LOWORD(lParam); int IsWindowMenu=HIWORD(lParam); //char txt[200]={0}; //sprintf(txt,"OnInitMenuPopUp:menu:%d,Index:%d,IsWindow:%d\n",wParam,index,IsWindowMenu); //WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL); return 0; } UINT g_id=0; bool isChecked=true; void drawwithpen(HDC hdc) { HPEN pen=CreatePen(PS_DOT,1,RGB(255,0,0)); //HBRUSH brush=CreateSolidBrush(RGB(0,0,200)); //HBRUSH brush=CreateHatchBrush(HS_CROSS,RGB(0,0,200)); HGDIOBJ brush=GetStockObject(NULL_BRUSH);//透明画刷,不需要删除 HGDIOBJ oldbrush= SelectObject(hdc,brush); HGDIOBJ oldpen= SelectObject(hdc,pen); HFONT font=CreateFont(30,0,45,0,1400, true,false,false,GB2312_CHARSET, 0,0,0,0,"华文新魏");// 字体名称(在C:\Windows\Fonts 打开具体的字体再看第一行名称) HGDIOBJ oldfont= SelectObject(hdc,font); SetTextColor(hdc,RGB(255,0,0)); SetBkColor(hdc,RGB(0,0,200)); //SetBkMode(hdc,TRANSPARENT);//背景透明 Ellipse(hdc,100,100,200,200); char a[50]="文字"; TextOut(hdc,100,100,a,strlen(a)); SelectObject(hdc,oldpen); SelectObject(hdc,oldbrush); SelectObject(hdc,oldfont); DeleteObject(pen); DeleteObject(font); //DeleteObject(brush); } void drawbitmap(HDC hdc) { HBITMAP bitmap=LoadBitmap(g_hinstance,MAKEINTRESOURCE(IDB_BITMAP2)); HDC memdc=CreateCompatibleDC(hdc);//内存DC HGDIOBJ oldbmp= SelectObject(memdc,bitmap);//送位图到内存dc //MoveToEx(memdc,100,100,NULL); //LineTo(memdc,130,150); BITMAP bm={0}; GetObject(bitmap,sizeof(bm),&bm); BitBlt(hdc,0,0,bm.bmWidth,bm.bmHeight,memdc,0,0,SRCCOPY);//在窗口中成像(显示) StretchBlt(hdc,100,300,69,51,memdc,0,0,138,102,SRCCOPY);//缩小显示 StretchBlt(hdc,100,400,276,204,memdc,0,0,138,102,SRCCOPY);//放大显示 //NOTSRCCOPY 反色/SRCCOPY 原图颜色 SelectObject(memdc,oldbmp);//还原默认 DeleteObject(bitmap);//删除位图 DeleteObject(memdc);//删除内存dc } void OnPaint(HWND hwnd) { PAINTSTRUCT ps={0}; HDC hdc=BeginPaint(hwnd,&ps); HICON ico=LoadIcon(g_hinstance,MAKEINTRESOURCE(IDI_ICON1)); //int oldmm=SetMapMode(hdc,MM_TWIPS); switch(g_id) { //SetPixel(hdc,100,100,RGB(0,0,255));//画点 case ID_drawline://画线 MoveToEx(hdc,100,100,NULL); LineTo(hdc,100,150); LineTo(hdc,150,150); break; case ID_drawellipse://画圆 Ellipse(hdc,100,100,200,200); RoundRect(hdc,300,100,500,300,200,200); break; case ID_drawrect://画距形 Rectangle(hdc,100,100,200,200); RoundRect(hdc,300,100,500,300,0,0); break; case ID_drawarc://画弧形 SetArcDirection(hdc,AD_CLOCKWISE);//AD_CLOCKWISE/AD_COUNTERCLOCKWISE 顺时针或逆时针 Arc(hdc,100,100,300,300,100,100,300,300); break; case ID_drawwithpen://使用画笔 drawwithpen(hdc); break; case ID_drawbitmap: drawbitmap(hdc); break; } //SetMapMode(hdc,oldmm); EndPaint(hwnd,&ps); } void On_Command(HWND hwnd,WPARAM wparam) { bool IsFromMenu=(HIWORD(wparam)==0?true:false);//点击菜单:0,加速键:1 unsigned int id=LOWORD(wparam); g_id=id; switch(id) { case IDFileOpen: MessageBox(hwnd,"open","info",MB_OK); break; case IDSet: MessageBox(hwnd,"ctrl+M","info",MB_OK); break; case ID_drawellipse: case ID_drawline: case ID_drawrect: case ID_drawarc: case ID_drawwithpen: case ID_drawbitmap: InvalidateRect(hwnd,NULL,TRUE); break; } } void OnSysCommand(HWND hwnd,WPARAM wparam) { } void OnSetCursor(HWND hwnd,WPARAM wparam,LPARAM lparam) { UINT hit=LOWORD(lparam); HCURSOR c1=NULL; if(hit==HTCLIENT)//光标在客户区 { POINT pt={0}; RECT rc={0}; GetCursorPos(&pt); GetClientRect(hwnd,&rc); // char txt[200]={0}; // ScreenToClient(hwnd,&pt); // sprintf(txt,"%d,%d ; %d,%d,%d,%d\n",pt.x,pt.y,rc.top,rc.left,rc.right,rc.bottom); // // WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL); if(pt.x>=rc.right/2)//客户区域前半部分与后半部分鼠标图标设置为不同 { //c1=LoadCursor(g_hinstance,MAKEINTRESOURCE(IDC_CUR_INPUT)); c1=LoadCursorFromFile("aero_working.ani");//从文件加载 } else { c1=LoadCursor(g_hinstance,MAKEINTRESOURCE(IDC_CUR_ARROW)); } } else { c1=LoadCursor(g_hinstance,MAKEINTRESOURCE(IDC_CUR_ARROW)); } if(c1!=NULL) SetCursor(c1); } //回调函数 LRESULT CALLBACK WinProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam) { switch(msg) { case WM_SYSCOMMAND: if(wparam==SC_CLOSE){ int ret=MessageBox(NULL,"是否退出","info",MB_YESNO); if(ret==IDYES){ //下面代码会自动关闭和销毁 //PostQuitMessage(0); } else return 0;//不执行下面代码 } OnSysCommand(hwnd,wparam); break; //在创建窗口之后还未显示的时候 case WM_CREATE: OnCreate(hwnd,lparam); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_COMMAND: On_Command(hwnd,wparam); break; case WM_INITMENUPOPUP: OnInitMunuPopUp(hwnd,msg,wparam,lparam); break; case WM_RBUTTONUP: //OnRButtonUp(hwnd,lparam); break; case WM_CONTEXTMENU: //OnContextMenu(hwnd,lparam); break; case WM_PAINT: OnPaint(hwnd); break; case WM_SETCURSOR: OnSetCursor(hwnd,wparam,lparam); return 0; break; } return DefWindowProc(hwnd,msg,wparam,lparam); } //注册窗口类 BOOL Register(LPSTR lpClassName,WNDPROC wndproc) { WNDCLASSEX wce={0}; wce.cbSize=sizeof(wce); wce.cbClsExtra=200; wce.cbWndExtra=200; wce.hbrBackground=CreateSolidBrush(RGB(0,0,255)); wce.hCursor=LoadCursor(g_hinstance,MAKEINTRESOURCE(IDC_CUR_ARROW)); wce.hIcon=NULL; wce.hIconSm=LoadIcon(g_hinstance,MAKEINTRESOURCE(IDI_ICON1)); wce.hInstance=g_hinstance; wce.lpfnWndProc=wndproc; wce.lpszClassName=lpClassName; wce.lpszMenuName=NULL;//MAKEINTRESOURCE(IDR_MENUMAIN); wce.style=CS_HREDRAW|CS_VREDRAW; ATOM atom= RegisterClassEx(&wce); if(atom==0){ MessageBox(NULL,"注册失败","info",MB_OK); return FALSE; } return TRUE; } //创建窗口 HWND CreateMain(LPSTR lpClassName,LPSTR lpWndName) { HMENU menumain= LoadMenu(g_hinstance,MAKEINTRESOURCE(IDR_MENUMAIN)); HWND hwnd=CreateWindowEx(0,lpClassName,lpWndName,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT,NULL,menumain,g_hinstance,"hello create"); return hwnd; } //创建子窗口 HWND CreateChild(HWND phwnd,LPSTR lpClassName,LPSTR lpWndName) { if(Register(lpClassName,DefWindowProc)==0) { MessageBox(phwnd,"创建子窗口失败","info",MB_OK); return NULL; } //子窗口风格,都要 WS_CHILD|WS_VISIBLE HWND hwnd=CreateWindowEx(0,lpClassName,lpWndName,WS_CHILD|WS_VISIBLE|WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT, 200,200,phwnd,NULL,g_hinstance,NULL); return hwnd; } //显示窗口 void Display(HWND hwnd) { ShowWindow(hwnd,SW_SHOW); UpdateWindow(hwnd); } //处理消息 void MSGdeal() { MSG msg={0}; HACCEL acc= LoadAccelerators( g_hinstance,MAKEINTRESOURCE(IDR_ACCELERATOR1)); while(GetMessage(&msg,NULL,0,0)){ if(!TranslateAccelerator(msg.hwnd,acc,&msg))//不是加速键 { TranslateMessage(&msg);//翻译消息 DispatchMessage(&msg);//派发给 WinProc 处理消息 } } } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { AllocConsole();//调试程序方法 g_houtput=GetStdHandle(STD_OUTPUT_HANDLE); g_hinstance=hInstance; // TODO: Place code here. if(Register("main",WinProc)==0) { MessageBox(NULL,"注册失败","提示",MB_OK); return 0; } char title[30]={0}; LoadString(g_hinstance,IDS_WND,title,sizeof(title)); HWND hwnd= CreateMain("main",title); Display(hwnd); MSGdeal(); return 0; }