【C】用C语言实现的VB的PictureBox
作者:0xAA55来源:http://www.0xaa55.com/thread-1417-1-1.html
转载请注明出处。
如图所示。这并不和VB的完全一样。它能显示图片,以及拉伸显示图片,除此以外,还能开启“自动重绘”模式。在自动重绘模式下用户需要通过调用函数取得hDC进行绘图操作。这样这东西就内置了一个画板。
头文件的代码:#ifndef _PictureBoxHeader_
#define _PictureBoxHeader_
#include<Windows.h>
//PictureBox的额外属性结构
//读取方式:(PicBoxAttr_p)GetWindowLong(hPicBox,GWL_USERDATA);
typedef struct
{
DWORD dwSign; //签名
HINSTANCE hInst; //实例句柄
HWND hWnd; //窗口句柄
HBRUSH BkBrush; //背景色
HDC hCtlDC; //控件HDC
HDC hPicDC; //图像HDC
HBITMAP hPicBmp; //图像
LONG lPicW; //图像宽度
LONG lPicH; //图像高度
HDC hImgDC; //后台图像HDC
HBITMAP hImgBmp; //后台图像
void *pImgBits; //后台图像位图数据
LONG lImgW; //后台图像宽度
LONG lImgH; //后台图像镐度
BOOL bStretch; //是否拉伸
BOOL bAutoRedraw;//是否自动重绘
}PicBoxAttr_t,*PicBoxAttr_p;
//注册PictureBox窗口类
ATOM WINAPI RegisterPictureBox();
//创建PictureBox控件
HWND WINAPI CreatePictureBox(int x,int y,int w,int h,HWND hParent,WORD ID);
//加载PictureBox的图像
BOOL WINAPI LoadPicture(HWND hWnd,TCHAR*szPicFile);
//判断是否为PictureBox控件
BOOL WINAPI IsPictureBox(HWND hWnd);
//设置PictureBox控件是否拉伸图像
void WINAPI SetPicBoxStretchMode(HWND hWnd,BOOL bStretch);
//设置PictureBox控件是否自动重绘
void WINAPI SetPicBoxAutoRedrawMode(HWND hWnd,BOOL bAutoRedraw);
//取得PictureBox的绘图句柄
HDC WINAPI GetPicBoxHDC(HWND hWnd);
//显示PictureBox的图像
void WINAPI RefreshPicBox(HWND hWnd);
//设置PictureBox的边框样式
void WINAPI SetPicBoxBorderMode(HWND hWnd,BOOL bShowBorder);
//清屏
void WINAPI ClearPicBoxImage(HWND hWnd);
//删除图片框的图片
void WINAPI DeletePicBoxPicture(HWND hWnd);
#endif // !_PictureBoxHeader_实现部分的代码:#include"picbox.h"
static ATOM g_ClassAtom=0;
const TCHAR g_szPicBoxClass[]=TEXT("PictureBox");
const DWORD PicBoxSign=0x091C7B08;
#define CalcPitch(w,b) ((((w)*(b)-1)/32+1)*4)
//=============================================================================
//函数:CreatePicBoxAttr
//描述:创建PictureBox属性块
//-----------------------------------------------------------------------------
static
PicBoxAttr_p CreatePicBoxAttr(HWND hWnd)
{
PicBoxAttr_p pAttr=(PicBoxAttr_p)malloc(sizeof(PicBoxAttr_t));
if(pAttr)
{
memset(pAttr,0,sizeof(PicBoxAttr_t));
pAttr->dwSign=PicBoxSign;
pAttr->hInst=GetModuleHandle(NULL);
pAttr->hWnd=hWnd;
pAttr->BkBrush=(HBRUSH)(COLOR_BTNFACE+1);
pAttr->hCtlDC=GetWindowDC(hWnd);
}
return pAttr;
}
//=============================================================================
//函数:DeletePicBoxAttr
//描述:删除PictureBox属性块
//-----------------------------------------------------------------------------
static
void DeletePicBoxAttr(PicBoxAttr_p pAttr)
{
if(pAttr)
{
//释放控件HDC
if(pAttr->hCtlDC)
ReleaseDC(pAttr->hWnd,pAttr->hCtlDC);
//删除图像
if(pAttr->hPicBmp)DeleteObject(pAttr->hPicBmp);
if(pAttr->hPicDC)DeleteDC(pAttr->hPicDC);
//删除后台图像
if(pAttr->hImgBmp)DeleteObject(pAttr->hImgBmp);
if(pAttr->hImgDC)DeleteDC(pAttr->hImgDC);
//释放内存
free(pAttr);
}
}
//=============================================================================
//函数:SetupPicBoxImage
//描述:重置PictureBox的后台图像
//-----------------------------------------------------------------------------
static
BOOL SetupPicBoxImage(PicBoxAttr_p pAttr)
{
RECT rc;
BITMAPINFOHEADER BMIF;
HDC hWindowDC;
HDC hNewDC=NULL;
HBITMAP hNewBMP=NULL;
void*pBits;
//创建一个新的HDC和HBITMAP
hWindowDC=GetWindowDC(pAttr->hWnd);
hNewDC=CreateCompatibleDC(hWindowDC);
ReleaseDC(pAttr->hWnd,hWindowDC);
if(!hNewDC)
return FALSE;
GetClientRect(pAttr->hWnd,&rc);
BMIF.biSize=sizeof(BMIF);
BMIF.biWidth=rc.right-rc.left;
BMIF.biHeight=rc.bottom-rc.top;
BMIF.biPlanes=1;
BMIF.biBitCount=24;
BMIF.biCompression=0;
BMIF.biSizeImage=CalcPitch(BMIF.biWidth,BMIF.biBitCount)*BMIF.biHeight;
BMIF.biXPelsPerMeter=0;
BMIF.biYPelsPerMeter=0;
BMIF.biClrUsed=0;
BMIF.biClrImportant=0;
hNewBMP=CreateDIBSection(hNewDC,(BITMAPINFO*)&BMIF,DIB_PAL_COLORS,&pBits,
NULL,0);
if(!hNewBMP)
goto Failed;
SelectObject(hNewDC,hNewBMP);
//填充为背景色,然后搬运旧的后台图像
FillRect(hNewDC,&rc,pAttr->BkBrush);
if(pAttr->hImgDC)
{
BitBlt(hNewDC,0,0,pAttr->lImgW,pAttr->lImgH,pAttr->hImgDC,0,0,SRCCOPY);
DeleteDC(pAttr->hImgDC);
}
else if(pAttr->hPicDC)
BitBlt(hNewDC,0,0,pAttr->lPicW,pAttr->lPicH,pAttr->hPicDC,0,0,SRCCOPY);
if(pAttr->hImgBmp)
DeleteObject(pAttr->hImgBmp);
//替换为新的后台图像
pAttr->lImgW=BMIF.biWidth;
pAttr->lImgH=BMIF.biHeight;
pAttr->hImgBmp=hNewBMP;
pAttr->hImgDC=hNewDC;
pAttr->pImgBits=pBits;
return TRUE;
Failed:
if(hNewBMP)
DeleteObject(hNewBMP);
if(hNewDC)
DeleteDC(hNewDC);
return FALSE;
}
//=============================================================================
//函数:LoadPicture
//描述:加载PictureBox的图像
//-----------------------------------------------------------------------------
BOOL WINAPI LoadPicture(HWND hWnd,TCHAR*szPicFile)
{
PicBoxAttr_p pAttr;
BITMAP bmp;
if(IsPictureBox(hWnd))
pAttr=(PicBoxAttr_p)GetWindowLongPtr(hWnd,GWL_USERDATA);
else
return FALSE;
//创建HDC,然后清除之前加载过的图像
if(!pAttr->hPicDC)
{
HDC hDC=GetWindowDC(hWnd);
pAttr->hPicDC=CreateCompatibleDC(hDC);
ReleaseDC(hWnd,hDC);
}
if(pAttr->hPicBmp)
DeleteObject(pAttr->hPicBmp);
//加载图像
pAttr->hPicBmp=(HBITMAP)LoadImage(pAttr->hInst,szPicFile,IMAGE_BITMAP,0,0,
LR_LOADFROMFILE|LR_CREATEDIBSECTION);
if(!pAttr->hPicBmp)
return FALSE;
SelectObject(pAttr->hPicDC,pAttr->hPicBmp);
GetObject(pAttr->hPicBmp,sizeof(bmp),&bmp);
pAttr->lPicW=bmp.bmWidth;
pAttr->lPicH=bmp.bmHeight;
RefreshPicBox(hWnd);
return TRUE;
}
//=============================================================================
//函数:RefreshPicBox
//描述:显示PictureBox的图像
//-----------------------------------------------------------------------------
void WINAPI RefreshPicBox(HWND hWnd)
{
RECT rc;
GetClientRect(hWnd,&rc);
InvalidateRect(hWnd,&rc,TRUE);
}
//=============================================================================
//函数:PicBoxWndProc
//描述:PictureBox的消息处理函数
//-----------------------------------------------------------------------------
static
LRESULT CALLBACK PicBoxWndProc(HWND hWnd,UINT Msg,WPARAM wp,LPARAM lp)
{
PicBoxAttr_p pAttr=NULL;
switch(Msg)
{
case WM_CREATE:
pAttr=CreatePicBoxAttr(hWnd);
if(pAttr)
SetWindowLongPtr(hWnd,GWL_USERDATA,(LONG_PTR)pAttr);
else
return-1;
break;
case WM_COMMAND:
hWnd=GetParent(hWnd);
if(hWnd)
return SendMessage(hWnd,Msg,wp,lp);
break;
case WM_PAINT:
pAttr=(PicBoxAttr_p)GetWindowLong(hWnd,GWL_USERDATA);
if(pAttr)
{
PAINTSTRUCT ps;
HDC hDC;
hDC=BeginPaint(hWnd,&ps);
if(pAttr->bAutoRedraw)//自动重绘的话,绘制后台图像
{
if(!pAttr->hImgDC || !pAttr->hImgBmp)
SetupPicBoxImage(pAttr);
BitBlt(hDC,0,0,pAttr->lImgW,pAttr->lImgH,
pAttr->hImgDC,0,0,SRCCOPY);
}
else//否则绘制图像
{
RECT rc;
GetClientRect(hWnd,&rc);
if(pAttr->bStretch)
{
SetStretchBltMode(hDC,HALFTONE);
StretchBlt(hDC,
rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,
pAttr->hPicDC,
0,0,pAttr->lPicW,pAttr->lPicH,SRCCOPY);
}
else
BitBlt(hDC,rc.left,rc.top,pAttr->lPicW,pAttr->lPicH,
pAttr->hPicDC,0,0,SRCCOPY);
}
EndPaint(hWnd,&ps);
}
break;
case WM_DESTROY:
pAttr=(PicBoxAttr_p)GetWindowLongPtr(hWnd,GWL_USERDATA);
if(pAttr)
DeletePicBoxAttr(pAttr);
SetWindowLongPtr(hWnd,GWL_USERDATA,0);
break;
default:
return DefWindowProc(hWnd,Msg,wp,lp);
}
return 0;
}
//=============================================================================
//函数:RegisterPictureBox
//描述:注册PictureBox窗口类
//-----------------------------------------------------------------------------
ATOM WINAPI RegisterPictureBox()
{
WNDCLASSEX WCEx=
{
sizeof(WNDCLASSEX),
0,
PicBoxWndProc,
0,
0,
GetModuleHandle(NULL),
NULL,
LoadCursor(NULL,MAKEINTRESOURCE(IDC_ARROW)),
(HBRUSH)(COLOR_BTNFACE+1),
NULL,
g_szPicBoxClass,
NULL
};
return g_ClassAtom=RegisterClassEx(&WCEx);
}
//=============================================================================
//函数:CreatePictureBox
//描述:创建PictureBox控件
//-----------------------------------------------------------------------------
HWND WINAPI CreatePictureBox(int x,int y,int w,int h,HWND hParent,WORD ID)
{
return CreateWindowEx(0,MAKEINTATOM(g_ClassAtom),NULL,
WS_CHILD|WS_VISIBLE|WS_BORDER,x,y,w,h,
hParent,(HMENU)ID,GetModuleHandle(NULL),NULL);
}
//=============================================================================
//函数:IsPictureBox
//描述:判断是否为PictureBox控件
//-----------------------------------------------------------------------------
BOOL WINAPI IsPictureBox(HWND hWnd)
{
# define nPicBox (sizeof(g_szPicBoxClass)/sizeof(TCHAR)-1)
TCHAR szPicBoxClass;
//首先判断窗口类
if(GetClassName(hWnd,szPicBoxClass,nPicBox+2) == nPicBox)
{
if(!lstrcmp(szPicBoxClass,g_szPicBoxClass))
{
//然后判断附加信息
PicBoxAttr_p pAttr
=(PicBoxAttr_p)GetWindowLong(hWnd,GWL_USERDATA);
if(!IsBadReadPtr(pAttr,sizeof(PicBoxAttr_t)))
{
if(pAttr->dwSign==PicBoxSign)
return TRUE;
}
}
}
return FALSE;
# undef nPicBox
}
//=============================================================================
//函数:SetPicBoxStretchMode
//描述:设置PictureBox控件是否拉伸图像
//-----------------------------------------------------------------------------
void WINAPI SetPicBoxStretchMode(HWND hWnd,BOOL bStretch)
{
if(IsPictureBox(hWnd))
{
PicBoxAttr_p pAttr;
pAttr=(PicBoxAttr_p)GetWindowLong(hWnd,GWL_USERDATA);
pAttr->bStretch=bStretch;
//强制重绘
RefreshPicBox(hWnd);
}
}
//=============================================================================
//函数:SetPicBoxAutoRedrawMode
//描述:设置PictureBox控件是否自动重绘
//-----------------------------------------------------------------------------
void WINAPI SetPicBoxAutoRedrawMode(HWND hWnd,BOOL bAutoRedraw)
{
if(IsPictureBox(hWnd))
{
PicBoxAttr_p pAttr=(PicBoxAttr_p)GetWindowLong(hWnd,GWL_USERDATA);
pAttr->bAutoRedraw=bAutoRedraw;
if(bAutoRedraw)
SetupPicBoxImage(pAttr);
}
}
//=============================================================================
//函数:GetPicBoxHDC
//描述:取得PictureBox的绘图句柄
//-----------------------------------------------------------------------------
HDC WINAPI GetPicBoxHDC(HWND hWnd)
{
if(IsPictureBox(hWnd))
{
PicBoxAttr_p pAttr=(PicBoxAttr_p)GetWindowLong(hWnd,GWL_USERDATA);
if(pAttr->bAutoRedraw)
return pAttr->hImgDC;
else
return pAttr->hCtlDC;
}
return NULL;
}
//=============================================================================
//函数:SetPicBoxBorderMode
//描述:设置PictureBox的边框样式
//-----------------------------------------------------------------------------
void WINAPI SetPicBoxBorderMode(HWND hWnd,BOOL bShowBorder)
{
if(IsPictureBox(hWnd))
{
if(bShowBorder)
SetWindowLong(hWnd,GWL_STYLE,GetWindowLong(hWnd,GWL_STYLE)|WS_BORDER);
else
SetWindowLong(hWnd,GWL_STYLE,GetWindowLong(hWnd,GWL_STYLE)&~WS_BORDER);
RefreshPicBox(hWnd);
}
}
//=============================================================================
//函数:ClearPicBoxImage
//描述:清屏
//-----------------------------------------------------------------------------
void WINAPI ClearPicBoxImage(HWND hWnd)
{
if(IsPictureBox(hWnd))
{
PicBoxAttr_p pAttr=(PicBoxAttr_p)GetWindowLong(hWnd,GWL_USERDATA);
if(pAttr->bAutoRedraw && pAttr->hImgDC)
{
RECT rc;
GetClientRect(hWnd,&rc);
FillRect(pAttr->hImgDC,&rc,pAttr->BkBrush);
if(pAttr->hPicDC && pAttr->hPicBmp)
BitBlt(pAttr->hImgDC,0,0,pAttr->lPicW,pAttr->lPicH,
pAttr->hPicDC,0,0,SRCCOPY);
}
RefreshPicBox(hWnd);
}
}
//=============================================================================
//函数:DeletePicBoxPicture
//描述:删除图片框的图片
//-----------------------------------------------------------------------------
void WINAPI DeletePicBoxPicture(HWND hWnd)
{
if(IsPictureBox(hWnd))
{
PicBoxAttr_p pAttr=(PicBoxAttr_p)GetWindowLong(hWnd,GWL_USERDATA);
if(pAttr->bAutoRedraw)
{
RECT rc;
GetClientRect(hWnd,&rc);
FillRect(pAttr->hImgDC,&rc,pAttr->BkBrush);
}
DeleteObject(pAttr->hPicBmp);pAttr->hPicBmp=NULL;
DeleteDC(pAttr->hPicDC);pAttr->hPicDC=NULL;
RefreshPicBox(hWnd);
}
}引用的例子:#include<Windows.h>
#include"picbox.h"
LRESULT CALLBACK WndProc(HWND hWnd,UINT Msg,WPARAM wp,LPARAM lp)
{
switch(Msg)
{
default:
return DefWindowProc(hWnd,Msg,wp,lp);
case WM_CREATE:
RegisterPictureBox();
do
{
HWND hPicBox1,hPicBox2;
hPicBox1=CreatePictureBox(0,0,300,300,hWnd,1);
LoadPicture(hPicBox1,TEXT("tex1.bmp"));
hPicBox2=CreatePictureBox(300,0,400,400,hWnd,1);
LoadPicture(hPicBox2,TEXT("tex1.bmp"));
SetPicBoxStretchMode(hPicBox2,TRUE);
}while(0);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR szCmd,int nCmd)
{
WNDCLASSEX WCEx={sizeof(WNDCLASSEX),0,WndProc,0,0,hInst,LoadIcon(NULL,MAKEINTRESOURCE(IDI_APPLICATION)),LoadCursor(NULL,MAKEINTRESOURCE(IDC_ARROW)),(HBRUSH)COLOR_BTNFACE,NULL,TEXT("tutpicbox"),NULL};//窗口类
MSG msg;
HWND hWnd=CreateWindowEx(0,MAKEINTATOM(RegisterClassEx(&WCEx)),TEXT("tutpicbox"),WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInst,NULL);//窗口句柄
ShowWindow(hWnd,nCmd);
UpdateWindow(hWnd);
while(GetMessage(&msg,NULL,0,0))//消息循环
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}BIN:
SRC: 这么复杂的玩意 我要怎么结合到A5UI里呢!!! 美俪女神 发表于 2015-7-15 03:01
这么复杂的玩意 我要怎么结合到A5UI里呢!!!
这其实就是一个自制控件而已。 可以转载么? icqw 发表于 2015-7-15 22:24
可以转载么?
可以。请注明作者和原网址。 0xAA55 发表于 2015-7-15 23:05
可以。请注明作者和原网址。
嗯嗯 ,了解。 已更新:
添加删除图片、清屏等功能。
修复窗口类判断不严谨的漏洞。 很方便的模板 thx 有什么好处啊? 可以提高重绘速度吗
页:
[1]