window-贴图技术

看了浅墨大哥的博客,有很多感悟,zu
摘要由CSDN通过智能技术生成

看了浅墨大哥的博客,有很多感悟,筑梦逐梦中~


首先需要有个window主进程函数:

int WINAPI WinMain(HINSTANCE hinstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nComShow){
}
窗体过程函数:
LRESULT CALLBACK  WindowProc(HWND hWnd,UINT msg,WPARAM wparam,LPARAM lparam);


其实:

#define CALLBACK    __stdcall
#define WINAPI      __stdcall

他们等价的,


书写window程序:

一、需要构建窗体类的结构体WNDCLASSEX:

原型如下:

typedef struct tagWNDCLASSEXW {
    UINT        cbSize;
    /* Win 3.x */
    UINT        style;
    WNDPROC     lpfnWndProc;
    int         cbClsExtra;
    int         cbWndExtra;
    HINSTANCE   hInstance;
    HICON       hIcon;
    HCURSOR     hCursor;
    HBRUSH      hbrBackground;
    LPCWSTR     lpszMenuName;
    LPCWSTR     lpszClassName;
    /* Win 4.0 */
    HICON       hIconSm;
} WNDCLASSEXW, *PWNDCLASSEXW, NEAR *NPWNDCLASSEXW, FAR *LPWNDCLASSEXW;
通常这样子书写:

	WNDCLASSEX wndclass={0};
	wndclass.cbClsExtra=0;
	wndclass.cbSize=sizeof(WNDCLASSEX);//尺寸,固定
	wndclass.style=CS_HREDRAW;//style如下---
	wndclass.lpfnWndProc=WindowProc;//选择窗口过程
	wndclass.hInstance=hinstance;//属于哪个实例
	wndclass.hIcon=LoadIcon(NULL,IDI_HAND);//可以改变的ico
	wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);//背景画刷
	wndclass.lpszMenuName=NULL;
	wndclass.lpszClassName=L"absurd";//类名,注册
	wndclass.hIconSm=NULL;


style:

#define CS_VREDRAW          0x0001//当垂直长度改变或移动窗口时,重画整个窗口
#define CS_HREDRAW          0x0002//当水平长度改变或移动窗口时,重画整个窗口</span>
#define CS_DBLCLKS          0x0008//允许向窗口发送双击鼠标键的消息</span>
#define CS_OWNDC            0x0020//给予每个窗口实例它本身的DC。注意,尽管这样是很方便,但它必须慎重使用,因为每个DC大约要占800个字节的内存。</span>
#define CS_CLASSDC          0x0040// 该窗口类的所有窗口实例都共享一个窗口类DC</span>
#define CS_PARENTDC         0x0080//将子窗口的裁剪区域设置到父窗口的DC中去,这样子窗口便可以在父窗口上绘制自身。注意,这是子窗口还是从系统缓存中获取DC,而不是使用父窗口的DC。使用该风格可以提高系统性能。</span>
#define CS_NOCLOSE          0x0200// 禁止系统菜单的关闭选项</span>
#define CS_SAVEBITS         0x0800//以位图形式保存被该窗口遮挡的屏幕部分,这样当给窗口移动以后,系统便可以用该保存的位图恢复屏幕移动的相应部分,从而系统不用向被该窗口遮挡的窗口发送 WM_PAINT 消息。该特性对于菜单类型的窗口比较合适,因为它通常是简短的显示一下之后便消失。设置该特性将增加显示该窗口的时间,因为它通常要先分配保存位图的内存。</span>
#define CS_BYTEALIGNCLIENT  0x1000//在字节边界上(在x方向上)定位窗口的用户区域的位置</span>
#define CS_BYTEALIGNWINDOW  0x2000//在字节边界上(在x方向上)定位窗口的位置</span>
#define CS_GLOBALCLASS      0x4000//当调用CreateWindow 或 CreateWindowEx 函数来创建窗口时允许它的hInstance参数和注册窗口类时传递给RegisterClass 的 hInstance参数不同。如果不指定该风格,则这两个 hInstance 必须相同。</span>


二、注册窗体结构体

RegisterClassEx(&wndclass);

三、创建窗体:

HWND hwnd=CreateWindow(L"absurd",//已注册的窗体结构体类名
L"absurdwin",//窗体名
WS_CAPTION|WS_OVERLAPPEDWINDOW,//dwStyle
CW_USEDEFAULT,//左上角位置出现坐标x
CW_USEDEFAULT,//y
WINDOW_WIDTH,//宽
WINDOW_HEIGHT,//高(这里宽高都是我自定义的)
NULL,//hWndParent指向被创建窗口的父窗口或所有者窗口的句柄。若要创建一个子窗口或一个被属窗口,需提供一个有效的窗口句柄。这个参数对弹出式窗口是可选的。Windows NT 5.0;创建一个消息窗口,可以提供HWND_MESSAGE或提供一个己存在的消息窗口的句柄。
NULL,//hMenu菜单句柄,或依据窗口风格指明一个子窗口标识。对于层叠或弹出式窗口,hMenu指定窗口使用的菜单:如果使用了菜单类,则hMenu可以为NULL。对于子窗口,hMenu指定了该子窗口标识(一个整型量),一个对话框使用这个整型值将事件通知父类。应用程序确定子窗口标识,这个值对于相同父窗口的所有子窗口必须是唯一的。
hinstance,//hlnstance与窗口相关联的实例句柄
NULL//lpParam指向一个值的指针,该值传递给窗口WM_CREATE消息。该值通过在IParam参数中的CREATESTRUCT结构传递。如果应用程序调用CreateWindow创建一个MDI客户窗口,则lpParam必须指向一个CLIENTCREATESTRUCT结构。
);



dwStyle如下:

/*
 * Window Styles
 */
#define WS_OVERLAPPED       0x00000000L//产生一个层叠的窗口。一个层叠的窗口有一个标题条和一个边框。与WS_TILED风格相同。
#define WS_POPUP            0x80000000L//创建一个弹出式窗口。该风格不能与WS_CHILD风格同时使用.
#define WS_CHILD            0x40000000L//创建一个子窗口。这个风格不能与WS_POPUP风格合用。
#define WS_MINIMIZE         0x20000000L//
#define WS_VISIBLE          0x10000000L//创建一个初始状态为可见的窗口。
#define WS_DISABLED         0x08000000L//创建一个初始状态为禁止的子窗口。一个禁止状态的窗口不能接受来自用户的输入信息。
#define WS_CLIPSIBLINGS     0x04000000L//排除子窗口之间的相对区域,也就是,当一个特定的窗口接收到WM_PAINT消息时,WS_CLIPSIBLINGS 风格将所有层叠窗口排除在绘图之外,只重绘指定的子窗口。如果未指定WS_CLIPSIBLINGS风格,并且子窗口是层叠的,则在重绘子窗口的客户区时,就会重绘邻近的子窗口。
#define WS_CLIPCHILDREN     0x02000000L//<span style="text-indent: 28px;">当在父窗口内绘图时,排除子窗口区域。在创建父窗口时使用这个风格。</span>
#define WS_MAXIMIZE         0x01000000L//
#define WS_CAPTION          0x00C00000L  //<span style="text-indent: 28px;">创建一个有标题框的窗口(包括WS_BORDER风格)。   /* WS_BORDER | WS_DLGFRAME  */
#define WS_BORDER           0x00800000L//
#define WS_DLGFRAME         0x00400000L//<span style="text-indent: 28px;">创建一个带对话框边框风格的窗口。这种风格的窗口不能带标题条。
#define WS_VSCROLL          0x00200000L//<span style="text-indent: 28px;">创建一个有垂直滚动条的窗口。</span>
#define WS_HSCROLL          0x00100000L//<span style="text-indent: 28px;">创建一个有水平滚动条的窗口。</span>
#define WS_SYSMENU          0x00080000L//创建一个在标题条上带有的窗口,必须同时设定WS_CAPTION风格。</span>
#define WS_THICKFRAME       0x00040000L//<span style="text-indent: 28px;">创建一个可调边框的窗口,与WS_SIZEBOX风格相同。</span>
#define WS_GROUP            0x00020000L//<span style="text-indent: 28px;">指定一组控制的第一个控制。这个控制组由第一个控制和随后定义的控制组成,自第二个控制开始每个控制,具有WS_GROUP风格,每个组的第一个控制带有WS_TABSTOP风格,从而使用户可以在组间移动。用户随后可以使用光标在组内的控制间改变键盘焦点。</span>
#define WS_TABSTOP          0x00010000L//创建一个控制,这个控制在用户按下Tab键时可以获得键盘焦点。按下Tab键后使键盘焦点转移到下一具有WS_TABSTOP风格的控制。


#define WS_MINIMIZEBOX      0x00020000L/
#define WS_MAXIMIZEBOX      0x00010000L//创建一个具有最大化按钮的窗口。该风格不能与WS_EX_CONTEXTHELP风格同时出现,同时必须指定WS_SYSMENU风格。</span>

#define WS_TILED            WS_OVERLAPPED
#define WS_ICONIC           WS_MINIMIZE//创建一个初始状态为最小化状态的窗口。与WS_MINIMIZE风格相同。</span>
#define WS_SIZEBOX          WS_THICKFRAME//创建一个可调边框的窗口,与WS_THICKFRAME风格相同。</span>
#define WS_TILEDWINDOW      WS_OVERLAPPEDWINDOW

/*
 * Common Window Styles
 */
#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED     | \        //创建一个具有WS_OVERLAPPED,WS_CAPTION,WS_SYSMENU WS_THICKFRAME,WS_MINIMIZEBOX,WS_MAXIMIZEBOX风格的层叠窗口,与WS_TILEDWINDOW风格相同。
                             WS_CAPTION        | \
                             WS_SYSMENU        | \
                             WS_THICKFRAME     | \
                             WS_MINIMIZEBOX    | \
                             WS_MAXIMIZEBOX)

#define WS_POPUPWINDOW      (WS_POPUP          | \           //创建一个具有WS_BORDER,WS_POPUP,WS_SYSMENU风格的窗口,WS_CAPTION和WS_POPUPWINDOW必须同时设定才能使窗口某单可见。</span>
                             WS_BORDER         | \
                             WS_SYSMENU)

#define WS_CHILDWINDOW      (WS_CHILD)//和child相同


四、显示窗体并更新

ShowWindow(hwnd,SW_SHOW);
UpdateWindow(hwnd);


这里解释下后一个参数,就是显示的方式:

SW_FORCEMINIMIZE:在WindowNT5.0中最小化窗口,即使拥有窗口的线程被挂起也会最小化。在从其他线程最小化窗口时才使用这个参数。
SW_HIDE:隐藏窗口并激活其他窗口。
SW_MAXIMIZE:最大化指定的窗口。
SW_MINIMIZE:最小化指定的窗口并且激活在Z序中的下一个顶层窗口。
SW_RESTORE:激活并显示窗口。如果窗口最小化或最大化,则系统将窗口恢复到原来的尺寸和位置。在恢复最小化窗口时,应用程序应该指定这个标志。
SW_SHOW:在窗口原来的位置以原来的尺寸激活和显示窗口。
SW_SHOWDEFAULT:依据在STARTUPINFO结构中指定的SW_FLAG标志设定显示状态,STARTUPINFO 结构是由启动应用程序的程序传递给CreateProcess函数的。
SW_SHOWMAXIMIZED:激活窗口并将其最大化。
SW_SHOWMINIMIZED:激活窗口并将其最小化。
SW_SHOWMINNOACTIVE:窗口最小化,激活窗口仍然维持激活状态。
SW_SHOWNA:以窗口原来的状态显示窗口。激活窗口仍然维持激活状态。
SW_SHOWNOACTIVATE:以窗口最近一次的大小和状态显示窗口。激活窗口仍然维持激活状态。
SW_SHOWNORMAL:激活并显示一个窗口。如果窗口被最小化或最大化,系统将其恢复到原来的尺寸和大小。应用程序在第一次显示窗口的时候应该指定此标志。



五、消息投递

	MSG msg={0};

	while(msg.message!=WM_QUIT){//如果不是程序退出则消息循环
	
		if(PeekMessage(&msg,0,0,0,PM_REMOVE)){//四个参数,1.指向消息结构体(从线程取出的消息存放进去),2.指定接受哪个窗体,所有则0,3.要获取消息的最小值,4.要获取消息的最大值,0为全部,5.PM_NOREMOVE|PM_REMOVE,分别表示取消息后是否移走(no不移走)
			TranslateMessage(&msg);//将虚拟键消息转化为字符消息
			DispatchMessage(&msg);//分发一个消息给窗口
		}
	
	}

六、填写窗体过程函数

LRESULT CALLBACK  WindowProc(HWND hWnd,UINT msg,WPARAM wparam,LPARAM lparam){
		//HDC hdc;
	switch(msg){

			
	case WM_KEYDOWN://可以使用相关消息
	
		switch(wparam){
	case VK_ESCAPE:
			DestroyWindow(hWnd);
			break;
	case VK_UP:
		MessageBox(NULL,L"你好",L"h",0);
		Game_Clean(hWnd);
		break;
	}
		break;

	case WM_DESTROY:
		PostQuitMessage(0);//表明有线程终止请求
		break;
	default:
		return DefWindowProc(hWnd,msg,wparam,lparam);
	
	}
	return 0;

}

七、窗口类注销

	UnregisterClass(L"absurd",wndclass.hInstance);


接下来讲GDI的使用:

HDC hdc=GetDC(hwnd);//获取设备环境句柄
.....
ReleaseDC(hwnd,hdc);//释放

下面讲几个可以使用的GDI绘图工具:

HPEN	h_pen=CreatePen(PS_SOLID,//画笔样式
1,线条宽度
RGB(1,1,1)//颜色
);//创建画笔
HBRUSH	h_brush=CreateSolidBrush(RGB(rand()%256,rand()%256,rand()%256));//创建实心画刷
HBRUSH h_brush2=CreateHatchBrush(HS_CROSS,//阴影样式
RGB(rand()%256,rand()%256,rand()%256)//前景色颜色值
);



关于画笔样式

#define PS_SOLID            0//实线
#define PS_DASH             1       /* -------  */
#define PS_DOT              2       /* .......  */
#define PS_DASHDOT          3       /* _._._._  */
#define PS_DASHDOTDOT       4       /* _.._.._  */
#define PS_NULL             5
#define PS_INSIDEFRAME      6
#define PS_USERSTYLE        7
#define PS_ALTERNATE        8
#define PS_STYLE_MASK       0x0000000F

#define PS_ENDCAP_ROUND     0x00000000
#define PS_ENDCAP_SQUARE    0x00000100
#define PS_ENDCAP_FLAT      0x00000200
#define PS_ENDCAP_MASK      0x00000F00

#define PS_JOIN_ROUND       0x00000000
#define PS_JOIN_BEVEL       0x00001000
#define PS_JOIN_MITER       0x00002000
#define PS_JOIN_MASK        0x0000F000

#define PS_COSMETIC         0x00000000
#define PS_GEOMETRIC        0x00010000
#define PS_TYPE_MASK        0x000F0000

关于阴影样式:

/* Hatch Styles */
#define HS_HORIZONTAL       0       /* ----- */
#define HS_VERTICAL         1       /* ||||| */
#define HS_FDIAGONAL        2       /* \\\\\ */
#define HS_BDIAGONAL        3       /* / */
#define HS_CROSS            4       /* +++++ */
#define HS_DIAGCROSS        5       /* xxxxx */
#define HS_API_MAX          12


选择好画笔后,使用需要用到

SelectObject(hdc,//设备上下文
h_brush//被选用对象
);

DeleteObject(
h_brush//删除被选用对象
);


绘制图形和线条:

先移动画笔

MoveToEx(hdc,x,y,
NULL//用来存放上一次的点,LPPOINT类型
);



画线

LineTo(hdc,
x,//终点
y//终点
};

画矩形:

Rectangle(hdc,bfx,//左上角
bfy,
x,//右下角
y);



文字输出:

先设置字体

HFONT hfont=CreateFont(45,//高度
0,//宽度
0,//显示角度
0,//字体角度
2,//磅数
0,//是否为斜体
0,//是否带下划线
0,//是否带删除
GB2312_CHARSET,//字符集
0,//输出精度
0,//裁剪精度
0,//输出质量
0,//间距的字符集
L"微软雅黑");

然后
wchar_t text1[]=L"1222324";
SetBkMode(hdc,TRANSPARENT);//设置文字透明
SetTextColor(hdc,RGB(rand()%256,rand()%256,rand()%256));//文字颜色
TextOut(hdc,x,y,text1,wcslen(text1));//输出


如果想贴图:先载入图片HBITMAP  g_girl3=(HBITMAP)LoadImage(NULL,//NULL表示从硬盘,其他可以从内存句柄
L"GameMedia/girl3.bmp",IMAGE_BITMAP,//图片类型可以为.bmp .cur .ico
480,148,LR_LOADFROMFILE//表示从文件加载
);
//其次建立兼容DC,用来缓存
HDC g_mdc=CreateCompatibleDC(hdc);
//
DeleteDC(g_mdc);//删除设备环境
//No.3选用位图
SelectObject(g_mdc,g_hBitmap);
//No.4贴图
BitBlt(hdc,//目标设备
0,0,//目标方位xy
WINDOW_WIDTH,WINDOW_HEIGHT,//宽高
g_mdc,0,0,//源设备
SRCCOPY//直接拷贝
);
//另外一种常用于快速去背:
TransparentBlt(hdc,num2*60,WINDOW_HEIGHT-300,60,74,//目标
g_mdc,num2*60,0,60,74,//源
RGB(0,0,0)//需要被去背的颜色
);



 

关于拷贝方式:
#define SRCCOPY             (DWORD)0x00CC0020 /* dest = source                   */
#define SRCPAINT            (DWORD)0x00EE0086 /* dest = source OR dest           */
#define SRCAND              (DWORD)0x008800C6 /* dest = source AND dest          */
#define SRCINVERT           (DWORD)0x00660046 /* dest = source XOR dest          */
#define SRCERASE            (DWORD)0x00440328 /* dest = source AND (NOT dest )   */
#define NOTSRCCOPY          (DWORD)0x00330008 /* dest = (NOT source)             */
#define NOTSRCERASE         (DWORD)0x001100A6 /* dest = (NOT src) AND (NOT dest) */
#define MERGECOPY           (DWORD)0x00C000CA /* dest = (source AND pattern)     */
#define MERGEPAINT          (DWORD)0x00BB0226 /* dest = (NOT source) OR dest     */
#define PATCOPY             (DWORD)0x00F00021 /* dest = pattern                  */
#define PATPAINT            (DWORD)0x00FB0A09 /* dest = DPSnoo                   */
#define PATINVERT           (DWORD)0x005A0049 /* dest = pattern XOR dest         */
#define DSTINVERT           (DWORD)0x00550009 /* dest = (NOT dest)               */
#define BLACKNESS           (DWORD)0x00000042 /* dest = BLACK                    */
#define WHITENESS           (DWORD)0x00FF0062 /* dest = WHITE                    */
如果使用罩法去背,需要准备如下图片:



使用又半部分和背景相与贴图,左半在相或贴图,即可





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值