问下vc中bitbltmfc 加载位图图资源的问题

VC中怎么让加载的位图资源运动?
VC中怎么让加载的位图资源运动?
08-11-25 & 发布
我加载了一张小球的图片,现在我想让这个小球沿着与水平成45度夹角运动,当遇到边界的时候就反弹回来,仍与水平成45度。 下面是写好的一部分代码: #include &windows.h& #include &string.h& #include &stdlib.h& #include &stdio.h& int i=0; int x[50]; int y[50]; POINT LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); //定义变量 HDC //设备环境句柄 HDC //内存设备环境句柄 HBITMAP hBm; //位图句柄 BITMAP //BITMAP结构 int WINAPI WinMain( HINSTANCE hInstance,HINSTANCE hPrevInst,LPSTR lpszCmdLine,int nCmdShow) { HWND MSG M WNDCLASS char lpszClassName[] = &位图&; char lpszTitle[]= &小球运动&; wndclass.style = 0; wndclass.lpfnWndProc = WndP wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hI wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION) ; wndclass.hCursor = LoadCursor( NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH) ; wndclass.lpszMenuName = NULL ; wndclass.lpszClassName = lpszClassN if( !RegisterClass( &wndclass)) { MessageBeep(0) ; return FALSE ; } hwnd = CreateWindow( lpszClassName, lpszTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ; //加载位图 hBm=LoadBitmap(hInstance,&pic&); //获取位图尺寸 GetObject( hBm, sizeof( BITMAP), (LPVOID)&bm) ; ShowWindow( hwnd, nCmdShow) ; UpdateWindow(hwnd); while( GetMessage(&Msg, NULL, 0, 0)) { TranslateMessage( &Msg) ; DispatchMessage( &Msg) ; } return Msg.wP } LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) { PAINTSTRUCT switch(message) { case WM_CREATE: //获取设备环境句柄 hdc=GetDC(hwnd); //获取内存设备环境句柄 hdcmem=CreateCompatibleDC(hdc); //释放设备环境句柄 ReleaseDC(hwnd,hdc); SetTimer(hwnd,1,40,NULL); GetCursorPos(&pt); for(i=0;i&50;i++) { x[i]=pt.x; y[i]=pt.y; }
case WM_PAINT: hdc=BeginPaint(hwnd,&ps); //将位图选入内存设备环境 SelectObject(hdcmem,hBm); //调用函数BitBlt将内存设备环境中的位图拷贝到设备环境中 BitBlt(hdc,0,200,bm.bmWidth,bm.bmHeight,hdcmem,0,0,SRCCOPY); //释放设备环境句柄 EndPaint(hwnd,&ps);
case WM_DESTROY: //释放位图 DeleteObject(hBm); PostQuitMessage(0);
default: return DefWindowProc(hwnd,message,wParam,lParam); } return 0; } 请帮忙看看。
请登录后再发表评论!CDC::BitBlt()
在VC中显示位图常用取BitBlt()方法,它是将一幅位图从一个设备场景复制到另一个。源和目标DC相互间必须兼容。
虽然此方法的功能是这样的,但是我一直没有理解网上一些例子代码,不知道其用到的各DC和位图如何得到,及它们之间的关系。
今天工作中要将一些位图显示到窗口中,所以重要学习了一下。
我已经将要用的位图导入到工程资源中,所以我可以用:
&&&&&&& CB
&&&&&&& cbmp.LoadBitmap(IDB_BMP1);
这样得到一个CBitmap对象。
&&&&&&& BITMAP
&&&&&&& cbmp.GetBitmap(&bitmap);
这样得到一个BITMAP对象,之所以要得到此对象是因为从其中可以得到位图的大小数据。
然后计算得到要在什么位置显示此位图(可以放在一个CR对象中)。
然后显示此位图,这是最重要的一步:
&&&&&&&& CDC dcM
&&&&&&&& dcMemory.CreateCompatibleDC(pDC);
&&&&&&&& hOldBitmap = dcMemory.SelectObject(&cbmp);
&&&&&&&&& pDC-&BitBlt(rect.left,
&&&&&&&&&&&&&&&&&&&&&&&&&&&& rect.top,
&&&&&&&&&&&&&&&&&&&&&&&&&&&& bitmap.bmWidth,
&&&&&&&&&&&&&&&&&&&&&&&&&&&& bitmap.bmHeight,
&&&&&&&&&&&&&&&&&&&&&&&&&&&& &dcMemory,
&&&&&&&&&&&&&&&&&&&&&&&&&&&& 0,0,
&&&&&&&&&&&&&&&&&&&&&&&&&&&& SRCCOPY);
其中pDC是一个CDC*,是将要在其中显示位图的设备环境。
这样位图就已经显示出来了,但是还要释放资源:
&&&&&&& cbmp.DeleteObject();
&&&&&&& dcMemory.SelectObject(hOldBitmap);
&&&&&&& dcMemory.DeleteDC();
其中,要将临时设备环境选择入初始时位图,否则将不能正确释放!!
要在一个设备环境中显示位图,不能直接在上面“画”(目前我是我么觉得的),需要创建一个与之相兼容的新设备环境然后将位图选择入些新设备环境,然后再从些新设备环境中拷备位图以显示到正确的设备环境中。而选入这个动作相当与已经将位图“画在了临时设备环境中”(实际上并没有画,否则就可以直接选入要画图的CDC了),而且选入后位图在临时设备环境中的位置是左上角!
转自:/user1/483/archives/.html
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:139152次
积分:3020
积分:3020
排名:第4635名
原创:119篇
转载:305篇
评论:14条2016人阅读
05月 13th, 2008 by 栏目类
我用MFC做了一个基于对话框的应用程序。 暂时只定两个控件,一个&打开&按钮,一个Picture控件。 功能简述:通过&打开&按钮,调用通用open对话框,来打开磁盘上的位图文件。并将位图显示在picture控件中。 相关文件如下: &&&&对话框头文件:finaltestdlg.h &&&对话框类实现:finaltestdlg.cpp &&& &&&通过打开对话框获取的文件名保存在filename。
下面描述的方法也是从网上找到的,程序调试运行都没有错误,就是不能将图片显示到picture控件中。 1.&在对话框头文件finaltestdlg.h中添加CBitmap&m_bmp;&创建一个对象。
2.&在初始化对话框函数BOOL&CFinaltestDlg::OnInitDialog()中添加了加载位图,获取位图信息,调整位图大小的代码。 如下:(前面关于位图的代码是加入的,其他代码由MFC生成) BOOL&CFinaltestDlg::OnInitDialog() { CDialog::OnInitDialog();
//位图加载 if(m_bmp.m_hObject!=NULL) m_bmp.DeleteObject();
HBITMAP&hbmp&=&(HBITMAP)::LoadImage(AfxGetInstanceHandle(),filename,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION &brvbarLR_LOADFROMFILE);
if&(hbmp==NULL) return&FALSE;
//获取加载的位图信息 m_bmp.Attach(hbmp); DIBSECTION& BITMAPINFOHEADER&&bminfo&=&ds.dsB m_bmp.GetObject(sizeof(ds),&ds);
int&cx&=&bminfo.biW&&&//获取图像宽度 int&cy&=&bminfo.biH&&//获取图像高度
//调整图像大小符合空间要求,使得其正好显示一张图片 CRect& GetDlgItem(IDC_STATIC1)-&GetWindowRect(&rect); ScreenToClient(&rect); GetDlgItem(IDC_STATIC1)-&MoveWindow(rect.left,rect.top,cx,cy,true);&&&//调整大小
//&Add&"About&"&menu&item&to&system&menu.
//&IDM_ABOUTBOX&must&be&in&the&system&command&range. ASSERT((IDM_ABOUTBOX&&&0xFFF0)&==&IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX& &&0xF000);
CMenu*&pSysMenu&=&GetSystemMenu(FALSE); if&(pSysMenu&!=&NULL) { CString&strAboutM strAboutMenu.LoadString(IDS_ABOUTBOX); if&(!strAboutMenu.IsEmpty()) { pSysMenu-&AppendMenu(MF_SEPARATOR); pSysMenu-&AppendMenu(MF_STRING,&IDM_ABOUTBOX,&strAboutMenu); } }
//&Set&the&icon&for&this&dialog.&&The&framework&does&this&automatically //&&when&the&application's&main&window&is&not&a&dialog SetIcon(m_hIcon,&TRUE); //&Set&big&icon SetIcon(m_hIcon,&FALSE); //&Set&small&icon
//&TODO:&Add&extra&initialization&here
return&TRUE;&&//&return&TRUE&&unless&you&set&the&focus&to&a&control }
3.&将位图绘制到picture控件,代码如下: void&CFinaltestDlg::OnPaint()& { if&(IsIconic()) { CPaintDC&dc(this);&//&device&context&for&painting
SendMessage(WM_ICONERASEBKGND,&(WPARAM)&dc.GetSafeHdc(),&0);
//&Center&icon&in&client&rectangle int&cxIcon&=&GetSystemMetrics(SM_CXICON); int&cyIcon&=&GetSystemMetrics(SM_CYICON); CRect& GetClientRect(&rect); int&x&=&(rect.Width()&-&cxIcon&+&1)&/&2; int&y&=&(rect.Height()&-&cyIcon&+&1)&/&2;
//&Draw&the&icon dc.DrawIcon(x,&y,&m_hIcon); } else { CDialog::OnPaint(); }
//以下代码为手动添加 CPaintDC&dc2(GetDlgItem(IDC_STATIC1)); CRect& GetDlgItem(IDC_STATIC1)-&GetClientRect(&rcclient); CDC& memdc.CreateCompatibleDC(&dc2); CBitmap& bitmap.CreateCompatibleBitmap(&dc2,rcclient.Width(),rcclient.Height()); memdc.SelectObject(&bitmap);
CWnd::DefWindowProc(WM_PAINT,(WPARAM)memdc.m_hDC,0);
CDC& maskdc.CreateCompatibleDC(&dc2); CBitmap& maskbitmap.CreateBitmap(rcclient.Width(),rcclient.Height(),1,1,NULL); maskdc.SelectObject(&maskbitmap); maskdc.BitBlt(0,0,rcclient.Width(),rcclient.Height(),&memdc,rcclient.left,rcclient.top,SRCCOPY);
CBrush& brush.CreatePatternBrush(&m_bmp); dc2.FillRect(rcclient,&brush);
dc2.BitBlt(rcclient.left,rcclient.top,rcclient.Width(),rcclient.Height(),&memdc,rcclient.left,rcclient.top,SRCPAINT); brush.DeleteObject(); }
PS:我试着把上面的2段位图操作代码分别添加到两个函数中,然后在点击open通用对话框&打开&的时候调用函数,也行不通。 如下:void&CFinaltestDlg::OnOpenFile()& { //&TODO:&Add&your&control&notification&handler&code&here char&szFileters[]&=&"Image&Files&(*.bmp) &brvbar*.txt &brvbarAll&files&(*.*) &brvbar*.* &brvbar &brvbar"; &&&&CFileDialog&opendlg&(TRUE,&"bmp",&"*.bmp",OFN_FILEMUSTEXIST& &brvbar&OFN_HIDEREADONLY,&szFileters,&this); &&&&if&(opendlg.DoModal()&==&IDOK)& { &&&&&&filename&=&opendlg.GetPathName(); &&BOOL&LoadImage(); &&void&displayPic(); }
希望高手赐教啊。我现在想转到使用文档窗口来操作了,后面还有很多事要做&&..可用分就那么点了,少了点见谅,哈哈
不难,待我给你两个示例。10分钟不到就可以解决。
你现在的工程应该是这个样子的:
你想要实现这样的:
非常感谢,呵呵。节省了不少时间,现在基本不用为界面发愁了。 开始算法了,
是,找对例子参考,可以节省很多时间。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:47831次
排名:千里之外
转载:24篇
(1)(2)(1)(2)(1)(3)(2)(3)(2)(1)(3)(2)(1)(5)(1)6379人阅读
一,只加载一张位图的方法:
装入bmp资源,id为IDB_BMP,按钮的bitmap属性设为true,icon属性为false。
CButton *pBtn = (CButton *)GetDlgItem(IDB_BMP);&CBitmap bitM&HBITMAP hB&if(bitMap.LoadBitmapW(IDB_NORMAL_BTN))&{&&hBit = (HBITMAP)bitMap.Detach();&&pBtn-&SetBitmap(hBit);&}
缺点:图片不会自动拉伸。
二,为按钮的不同状态加载不同的位图:(使用CBitmapButton类)这种方法还可以。1,按钮属性 Owner Draw选上,按钮ID: IDC_BUTTON1
为IDC_BUTTON1添加CButton变量m_button,2,然后手动将CButton m_button改为CBitmapButton m_3,在初始化里边m_button.LoadBitmaps(IDB_BITMAP1, IDB_BITMAP2);//IDB_BITMAP1:平时;IDB_BITMAP2:按下m_button.SubclassDlgItem(IDC_BUTTON1, this);m_button.SizeToContent();
或者用另一种方式,不必为IDC_BUTTON1添加关联的变量。直接声明CBitmapButton m_,在初始化里边调用
m_BitmapBtn.AutoLoad(IDC_BUTTON1_AREA,this);//把按钮和变量联系起来
m_BitmapBtn.LoadBitmaps(IDB_BITMAP1, IDB_BITMAP2);
m_button.SizeToContent();
缺点:1,无法显示文字,需重载DrawItem函数。
&&&&&&&&&&&&2,无法去掉图片的背景色,即只能显示矩形按钮。// NOTE: CMyButton is a class derived from CButton. The CMyButton
// object was created as follows:
// CMyButton myB
// myButton.Create(_T("My button"),
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|BS_OWNERDRAW,
CRect(10,10,100,30), pParentWnd, 1);
// This example implements the DrawItem method for a CButton-derived
// class that draws the button's text using the color red.
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
UINT uStyle = DFCS_BUTTONPUSH;
// This code only works with buttons.
ASSERT(lpDrawItemStruct-&CtlType == ODT_BUTTON);
// If drawing selected, add the pushed style to DrawFrameControl.
if (lpDrawItemStruct-&itemState & ODS_SELECTED)
uStyle |= DFCS_PUSHED;
// Draw the button frame.
::DrawFrameControl(lpDrawItemStruct-&hDC, &lpDrawItemStruct-&rcItem,
DFC_BUTTON, uStyle);
// Get the button's text.
CString strT
GetWindowText(strText);
// Draw the button text using the text color red.
COLORREF crOldColor = ::SetTextColor(lpDrawItemStruct-&hDC, RGB(255,0,0));
::DrawText(lpDrawItemStruct-&hDC, strText, strText.GetLength(),
&lpDrawItemStruct-&rcItem, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
::SetTextColor(lpDrawItemStruct-&hDC, crOldColor);
//继承CBitmapButton的例子
void & MyButton::DrawItem(LPDRAWITEMSTRUCT & lpDrawItemStruct) & { // & TODO: & Add & your & code & to & draw & the & specified & item //从lpDrawItemStruct获取控件的相关信息 CRect & rect=lpDrawItemStruct-& rcI CDC & *pDC=CDC::FromHandle(lpDrawItemStruct-& hDC); int & nSaveDC=pDC-& SaveDC(); UINT & state & = & lpDrawItemStruct-& itemS TCHAR & strText[MAX_PATH & + & 1]; ::GetWindowText(m_hWnd, & strText, & MAX_PATH); CBitmapButton::DrawItem(lpDrawItemStruct); CRect & rect1= rect.SetRect(rect1.left,rect1.top,rect1.left+75,rect1.top+24); //显示按钮的文本 pDC-& SetTextColor(TextColor); if & (strText!=NULL) { CFont* & hFont & = & GetFont(); CFont* & hOldFont & = & pDC-& SelectObject(hFont); CSize & szExtent & = & pDC-& GetTextExtent(strText, & lstrlen(strText)); CPoint & pt( & rect.CenterPoint().x & - & szExtent.cx & / & 2, & rect.CenterPoint().y & - & szExtent.cy & / & 2); if & (state & & & ODS_SELECTED) & pt.Offset(1, & 1); int & nMode & = & pDC-& SetBkMode(TRANSPARENT); if & (state & & & ODS_DISABLED) pDC-& DrawState(pt, & szExtent, & strText, & DSS_DISABLED, & TRUE, & 0, & (HBRUSH)NULL); else pDC-& DrawState(pt, & szExtent, & strText, & DSS_NORMAL, & TRUE, & 0, & (HBRUSH)NULL); pDC-& SelectObject(hOldFont); pDC-& SetBkMode(nMode); } pDC-& RestoreDC(nSaveDC); }
三,继承CButton类,重写OnPaint函数,为Button的不同状态画位图(BitBlt,TransparentBlt,StretchBlt ,MaskBlt,
四,可以采用CButtonST控件,挺好用的,比MFC的那些封装好用。假设按钮ID为IDC_BUTTON1 1.添加成员变量 CButtonST m_ 2.添加位图资源,ID设为IDB_BITMAP1 3.在OnInitDialog函数中初始化按钮m_btn.SubclassDlgItem(IDC_BUTTON1,this); m_btn.SetBitmaps(IDB_BITMAP1,RGB(0,0,0)); m_btn.OffsetColor(CButtonST::BTNST_COLOR_BK_IN, 30); 注: 上面的SetBitmaps函数会将图片中颜色值为RGB(0,0,0)的点设为透明。
把button按钮属性设置为ower draw然后映射onDrawItem消息在ondraw函数内自己绘制就可以了void CUi6Dlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct){if(nIDCtl == IDC_HELLO_CFAN){//绘制按钮框架UINT uStyle = DFCS_BUTTONPUSH;//是否按下去了?if (lpDrawItemStruct-&itemState & ODS_SELECTED)uStyle |= DFCS_PUSHED;CDCdc.Attach(lpDrawItemStruct-&hDC);dc.DrawFrameControl(&lpDrawItemStruct-&rcItem, DFC_BUTTON, uStyle);//输出文字dc.SelectObject(&m_Font);dc.SetTextColor(RGB(0, 0, 255));dc.SetBkMode(TRANSPARENT);CString sTm_HelloCFan.GetWindowText(sText);dc.TextOut(lpDrawItemStruct-&rcItem.left + 20, lpDrawItemStruct-&rcItem.top + 20, sText);//是否得到焦点if(lpDrawItemStruct-&itemState & ODS_FOCUS){//画虚框CRect rtFocus = lpDrawItemStruct-&rcIrtFocus.DeflateRect(3, 3);dc.DrawFocusRect(&rtFocus);}}CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);}
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:115148次
积分:1545
积分:1545
排名:第11888名
原创:19篇
转载:105篇
评论:19条
(2)(1)(1)(1)(5)(3)(5)(7)(2)(4)(29)(18)(10)(31)(5)----> 如何在vc++中旋转位图---任意角度
如何在vc++中旋转位图---任意角度
&&&&如何在vc++中旋转位图---任意角度网上有很多关于位图旋转的资料,但是讲得很清楚的不多(我没有仔细查找).于是我也写了一个,希望能给向我这样的初学者一点帮助.第一步,你必须知道位图即BMP格式的文件的结构.位图(bmp)文件由以下几个部分组成:1.BITMAPFILEHEADER,它的定义如下:typedefstructtagBITMAPFILEHEADER{WORDDWORDWORDWORDDWORDbfTbfS//必须为BM//文件大小&&&&&&&&bfReserved1;//必须为0bfReserved2;//必须为0bfOffB//从&&&&&&&&ITMAPFILEHEADER到存放bmp数据的偏移量&&&&&&&&}BITMAPFILEHEADER,*PBITMAPFILEHEADER;2.BITMAPINFOHEADER,它的定义如下:typedefstructtagBITMAPINFOHEADER{DWORDbiS//此结构的大小,可用sizeof(BITMAPINFOHEAER)得到LONG为单位LONG为单位WORDWORD可为0,1,4,8,24,32DWORDDWORDLONG象素数LONGbiYPelsPerM//一米纵向biCbiSizeI//(仅用于压缩)biXPelsPerM//一米横向biP//必须为1biBitC//位图象素位数,biH//位图高度,以象素biW//位图宽度,以象素&&&&&&&& 象素数DWORD色表)DWORDbiClrI}BITMAPINFOHEADER,*PBITMAPINFOHEADER;由于以上信息可以直接从MSDN上查到,所以只做简单介绍,你可以自己查看NSDN帮助,上面有很详细的介绍.3.DIB位图像.这里放的是真正的位图数据.知道了位图的存放格式,下面我们就可以很容易的把它读如内存.第二步,读入bmp图像LPCTSTRlpszFileName4=untitled.CF文件BITMAPFILEHEADERbfhH//bmp文件头BITMAPINFOHEADERbmiH//bmp格式头LPBITMAPINFOlpBitmapIintbmpWidth=0;intbmpHeight=0;//bmp格式具体信息//图片宽度//图片高度//文件路径//用于读取BMPbiClrU//(非零用语短颜&&&&&&&&if(!file.Open(lpszFileName,CFile::modeRead))&&&&&&&&//打开文件&&&&&&&&file.Read(bfhHeader,sizeof(BITMAPFILEHEADER));//读取文件头if(bfhHeader.bfType!=((WORD)(M8)|B))//判断是否是BMif(bfhHeader.bfSize!=file.GetLength())if(file.Read((LPSTR)bmiHeader,sizeof(bmiHeader))!=sizeof(bmiHeader))bmpHeight=bmiHeader.biH//得到高度和宽度&&&&&&&& bmpWidth=bmiHeader.biWfile.SeekToBegin();file.Read(bfhHeader,sizeof(BITMAPFILEHEADER));UINTuBmpInfoLen=(UINT)bfhHeader.bfOffBitssizeof(BITMAPFILEHEADER);lpBitmapInfo=(LPBITMAPINFO)newBYTE[uBmpInfoLen];file.Read((LPVOID)lpBitmapInfo,uBmpInfoLen);if((*(LPDWORD)(lpBitmapInfo))!=sizeof(BITMAPINFOHEADER))DWORDdwBitlen=bfhHeader.bfSize-bfhHeader.bfOffBLPVOIDlpSrcBits=newBYTE[dwBitlen];//将数据读入lpSrcBits数组file.ReadHuge(lpSrcBits,dwBitlen);file.Close();//关闭文件下面我们将图片显示在屏幕上:第三步,显示图片CClientDChDC(this);StretchDIBits(hDC,0,0,bmpWidth,bmpHeight,0,0,bmpWidth,bmpHeight,lpSrcBits,lpBitmapInfo,DIB_RGB_COLORS,SRCCOPY);第四步,将图片读入内存设备环境HDCdcSHBITMAPdcSrc=CreateCompatibleDC(hDC);//得到一个内存设备环境bitmap=CreateCompatibleBitmap(hDC,bmpWidth,bmpHeight);SelectObject(dcSrc,bitmap);BitBlt(dcSrc,0,0,bmpWidth,bmpHeight,hDC,0,0,SRCCOPY);//这一步很重要第五步,实现位图旋转我们假设旋转位图的函数原形如下:&&&&&&&& voidRotateBitmap(HDCdcSrc,intSrcWidth,intSrcHeight,doubleangle,HDCpDC);/*参数解释如下://///////////////////////////////////////////////////////////////////////////HDCdcSrc:要旋转的位图的内存设备环境,就是第四步创建的intSrcWidth:要旋转位图的宽度intSrcHeight:要旋转位图的高度doubleangle:所要旋转的角度,以弧度为单位HDCpDC:第三步得到的当前屏幕设备环境*/////////////////////////////////////////////////////////////////////////////////////////////////////////以下是函数实现细节voidRotateAnyAngle(HDCdcSrc,intSrcWidth,intSrcHeight,doubleangle){doublex1,x2,x3;doubley1,y2,y3;doublemaxWidth,maxHeight,minWidth,minHdoublesrcX,srcY;doublesinA,cosA;doubleDstWdoubleDstHHDCdcD//旋转后的内存设备环境HBITMAPnewBsinA=sin(angle);cosA=cos(angle);x1=-SrcHeight*sinA;y1=SrcHeight*cosA;x2=SrcWidth*cosA-SrcHeight*sinA;&&&&&&&& y2=SrcHeight*cosA+SrcWidth*sinA;x3=SrcWidth*cosA;y3=SrcWidth*sinA;minWidth=x3(x1x2?x2:x1)?(x1x2?x2:x1):x3;minWidth=minWidth0?0:minWminHeight=y3(y1y2?y2:y1)?(y1y2?y2:y1):y3;minHeight=minHeight0?0:minHmaxWidth=x3(x1x2?x1:x2)?x3:(x1x2?x1:x2);maxWidth=maxWidth0?maxWidth:0;maxHeight=y3(y1y2?y1:y2)?y3:(y1y2?y1:y2);maxHeight=maxHeight0?maxHeight:0;DstWidth=maxWidth-minWDstHeight=maxHeight-minHdcDst=CreateCompatibleDC(dcSrc);newBitmap=CreateCompatibleBitmap(dcSrc,(int)DstWidth,(int)DstHeight);SelectObject(dcDst,newBitmap);for(intI=0;IDstHI++){for(intJ=0;JDstWJ++){srcX=(J+minWidth)*cosA+(I+minHeight)*sinA;srcY=(I+minHeight)*cosA-(J+minWidth)*sinA;if((srcX=0)(srcX=SrcWidth)(srcY=0)(srcY=SrcHeight)){BitBlt(dcDst,J,I,1,1,dcSrc,(int)srcX,(int)srcY,SRCCOPY);}}}//显示旋转后的位图BitBlt(hDC,200,200,(int)DstWidth,(int)DstHeight,dcDst,0,0,SRCCOPY);&&&&&&&&DeleteObject(newBitmap);&&&&&&&& DeleteDC(dcDst);}最后我们调用就可以了:doubleangle=(45/180.0)*3.14159;//旋转45Degree,可为任意角度&&&&&&&&VC实现BMP位图文件结构及平滑缩放&&&&&&&&用普通方法显示BMP位图,占内存大,速度慢,在图形缩小时,失真严重,在低颜色位数的设备上显示高颜色位数的图形图形时失真大。本文采用视频函数显示BMP位图,可以消除以上的缺点。&&&&&&&&一、BMP文件结构1.BMP文件组成BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。2.BMP文件头BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。其结构定义如下:typedefstructtagBITMAPFILEHEADER{WORDbfT//位图文件的类型,必须为BMDWORDbfS//位图文件的大小,以字节为单位WORDbfReserved1;//位图文件保留字,必须为0&&&&&&&& WORDbfReserved2;//位图文件保留字,必须为0DWORDbfOffB//位图数据的起始位置,以相对于位图//文件头的偏移量表示,以字节为单位}BITMAPFILEHEADER;3.位图信息头BMP位图信息头数据用于说明位图的尺寸等信息。typedefstructtagBITMAPINFOHEADER{DWORDbiS//本结构所占用字节数LONGbiW//位图的宽度,以像素为单位LONGbiH//位图的高度,以像素为单位WORDbiP//目标设备的级别,必须为1WORDbiBitCount//每个像素所需的位数,必须是1(双色),//4(16色),8(256色)或24(真彩色)之一DWORDbiC//位图压缩类型,必须是0(不压缩),//1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一DWORDbiSizeI//位图的大小,以字节为单位LONGbiXPelsPerM//位图水平分辨率,每米像素数LONGbiYPelsPerM//位图垂直分辨率,每米像素数DWORDbiClrU//位图实际使用的颜色表中的颜色数DWORDbiClrI//位图显示过程中重要的颜色数&&&&&&&& }BITMAPINFOHEADER;4.颜色表颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:typedefstructtagRGBQUAD{BYTErgbB//蓝色的亮度(值范围为0-255)BYTErgbG//绿色的亮度(值范围为0-255)BYTErgbR//红色的亮度(值范围为0-255)BYTErgbR//保留,必须为0}RGBQUAD;颜色表中RGBQUAD结构数据的
个数有biBitCount来确定:当biBitCount=1,4,8时,分别有2,16,256个表项;当biBitCount=24时,没有颜色表项。位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:typedefstructtagBITMAPINFO{BITMAPINFOHEADERbmiH//位图信息头RGBQUADbmiColors[1];//颜色表}BITMAPINFO;5.位图数据&&&&&&&& 位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数:当biBitCount=1时,8个像素占1个字节;当biBitCount=4时,2个像素占1个字节;当biBitCount=8时,1个像素占1个字节;当biBitCount=24时,1个像素占3个字节;Windows规定一个扫描行所占的字节数必须是4的倍数(即以long为单位),不足的以0填充,一个扫描行所占的字节数计算方法:DataSizePerLine=(biWidth*biBitCount+31)/8;//一个扫描行所占的字节数DataSizePerLine=DataSizePerLine/4*4;//字节数必须是4的倍数位图数据的大小(不压缩情况下):DataSize=DataSizePerLine*biH二、BMP位图一般显示方法1.申请内存空间用于存放位图文件GlobalAlloc(GHND,FileLength);2.位图文件读入所申请内存空间中LoadFileToMemory(mpBitsSrc,mFileName);3.在OnPaint等函数中用创建显示用位图用CreateDIBitmap()创建显示用位图,用CreateCompatibleDC()创建兼容DC,用SelectBitmap()选择显示位图。4.用BitBlt或StretchBlt等函数显示位图&&&&&&&& 5.用DeleteObject()删除所创建的位图以上方法的缺点是:1)显示速度慢;2)内存占用大;3)位图在缩小显示时图形失真大,(可通过安装字体平滑软件来解决);4)在低颜色位数的设备上(如256显示模式)显示高颜色位数的图形(如真彩色)图形失真严重。三、BMP位图缩放显示用DrawDib视频函数来显示位图,内存占用少,速度快,而且还可以对图形进行淡化(Dithering)处理。淡化处理是一种图形算法,可以用来在一个支持比图像所用颜色要少的设备上显示彩色图像。BMP位图显示方法如下:1.打开视频函数DrawDibOpen(),一般放在在构造函数中2.申请内存空间用于存放位图文件GlobalAlloc(GHND,FileLength);3.位图文件读入所申请内存空间中LoadFileToMemory(mpBitsSrc,mFileName);4.在OnPaint等函数中用DrawDibRealize(),DrawDibDraw()显示位图5.关闭视频函数DrawDibClose(),一般放在在析构函数中以上方法的优点是:1)显示速度快;2)内存占用少;3)缩放显示时图形失真小,4)在低颜色位数的设备上显示高颜色位数的图形图形时失真小;5)通过直接处理位图数据,可以制作简单动画。四、CViewBimap类编程要点&&&&&&&&1.在CViewBimap类中添加视频函数等成员&&&&&&&& HDRAWDIBm_hDrawD//视频函数HANDLEmhBitsS//位图文件句柄(内存)LPSTRmpBitsS//位图文件地址(内存)BITMAPINFOHEADER*mpBitmapI//位图信息头2.在CViewBimap类构造函数中添加打开视频函数&&&&&&&&m_hDrawDib=DrawDibOpen();3.在CViewBimap类析构函数中添加关闭视频函数&&&&&&&&if(m_hDrawDib!=NULL){DrawDibClose(m_hDrawDib);m_hDrawDib=NULL;}4.在CViewBimap类图形显示函数OnPaint中添加GraphicDraw()&&&&&&&&voidCViewBitmap::OnPaint(){CPaintDCdc(this);//devicecontextforpaintingGraphicDraw();&&&&&&&& }voidCViewBitmap::GraphicDraw(void){CClientDCdc(this);//devicecontextforpaintingBITMAPFILEHEADER*pBitmapFileHULONGbfoffBits=0;CPointW//图形文件名有效(=0BMP)if(mBitmapFileTypeID_BITMAP_BMP)//图形文件名有效(=0BMP)//准备显示真彩位图pBitmapFileHeader=(BITMAPFILEHEADER*)mpBitsSbfoffBits=pBitmapFileHeader-bfOffB//使用普通函数显示位图if(m_hDrawDib==NULL||mDispMethod==0){HBITMAPhBitmap=::CreateDIBitmap(dc.m_hDC,mpBitmapInfo,CBM_INIT,mpBitsSrc+bfoffBits,(LPBITMAPINFO)mpBitmapInfo,DIB_RGB_COLORS);//建立位图&&&&&&&& HDChMemDC=::CreateCompatibleDC(dc.m_hDC);//建立内存HBITMAPhBitmapOld=SelectBitmap(hMemDC,hBitmap);//选择对象//成员CRectmDispR用于指示图形显示区域的大小.//成员CPointmPos用于指示图形显示起始位置坐标.if(mPos.x(mpBitmapInfo-biWidth-mDispR.Width()))mPos.x=mpBitmapInfo-biWidth-mDispR.Width();if(mPos.y(mpBitmapInfo-biHeight-mDispR.Height()))mPos.y=mpBitmapInfo-biHeight-mDispR.Height();if(mPos.x0)mPos.x=0;if(mPos.y0)mPos.y=0;if(mFullViewTog==0){//显示真彩位图::BitBlt(dc.m_hDC,0,0,mDispR.Width(),mDispR.Height(),hMemDC,mPos.x,mPos.y,SRCCOPY);}else{::StretchBlt(dc.m_hDC,0,0,mDispR.Width(),mDispR.Height(),hMemDC,0,0,mpBitmapInfo-biWidth,mpBitmapInfobiHeight,SRCCOPY);&&&&&&&& }//结束显示真彩位图::DeleteObject(SelectObject(hMemDC,hBitmapOld));//删除位图}else{//使用视频函数显示位图if(mPos.x(mpBitmapInfo-biWidth-mDispR.Width()))mPos.x=mpBitmapInfo-biWidth-mDispR.Width();if(mPos.y(mpBitmapInfo-biHeight-mDispR.Height()))mPos.y=mpBitmapInfo-biHeight-mDispR.Height();if(mPos.x0)mPos.x=0;if(mPos.y0)mPos.y=0;//显示真彩位图DrawDibRealize(m_hDrawDib,dc.GetSafeHdc(),TRUE);if(mFullViewTog==0){Wid.x=mDispR.Width();Wid.y=mDispR.Height();//1:1显示时,不能大于图形大小if(Wid.xmpBitmapInfo-biWidth)&&&&&&&& Wid.x=mpBitmapInfo-biWif(Wid.ympBitmapInfo-biHeight)Wid.y=mpBitmapInfo-biHDrawDibDraw(m_hDrawDib,dc.GetSafeHdc(),0,0,Wid.x,Wid.y,mpBitmapInfo,(LPVOID)(mpBitsSrc+bfoffBits),mPos.x,mPos.y,Wid.x,Wid.y,DDF_BACKGROUNDPAL);}else{DrawDibDraw(m_hDrawDib,dc.GetSafeHdc(),0,0,mDispR.Width(),mDispR.Height(),mpBitmapInfo,(LPVOID)(mpBitsSrc+bfoffBits),0,0,mpBitmapInfo-biWidth,mpBitmapInfo-biHeight,DDF_BACKGROUNDPAL);}}}五、使用CViewBimap类显示BMP位图&&&&&&&& 1.在VisualC++5.0中新建一个名称为mymap工程文件,类型为MFCAppWizard[exe]。在编译运行通过后,在WorkSpace(如被关闭,用Alt_0打开)点击ResourceView,点击Menu左侧的+符号展开Menu条目,双击IDR_MAINFRAME条目,进入菜单资源编辑,在“查看(V)”下拉式菜单(英文版为View下拉式菜单)的尾部添加“ViewBitmap”条目,其ID为ID_VIEW_BITMAP。2.在VisualC++5.0中点击下拉式菜单Project-AddToprojectFiles...,将Bitmap0.h和Bitmap0.cpp添加到工程文件中。3.在VisualC++5.0中按Ctrl_W进入MFCClassWizard,选择类名称为CMainFrame,ObjectIDs:ID_VIEW_BITMAP,Messages选择Command,然后点击AddFucction按钮,然后输入函数名为OnViewBimap。在添加OnViewBimap后,在Memberfunctions:中点击OnViewBimap条目,点击EditCode按钮编辑程序代码。代码如下:&&&&&&&&voidCMainFrame::OnViewBitmap(){//TODO:AddyourcommandhandlercodehereCViewBitmap*pViewBitmap=NULL;pViewBitmap=newCViewBitmap(BITMAP.BMP,this);pViewBitmap-ShowWindow(TRUE);&&&&&&&& }并在该程序的头部添加#includebitmap0.h,然后编译运行。4.找一个大一点的真彩色的BMP位图,将它拷贝到BITMAP.BMP中。5.运行时,点击下拉式菜单“查看(V)-ViewBitmap”(英文版为View-ViewBitmap)即可显示BITMAP.BMP位图。六、CViewBimap类功能说明1.在客户区中带有水平和垂直滚动条。在位图大小大于显示客户区时,可以使用滚动条;在位图大小小于显示客户区或全屏显示时,滚动条无效。2.在客户区中底部带有状态条。状态条中的第一格为位图信息,第二格为位图显示方法,可以是使用普通函数或使用视频函数。在第二格区域内点击鼠标,可在两者之间接换。第三格为位图显示比例,可以是1;1显示或全屏显示。在第三格区域内点击鼠标,可在两者之间接换。在全屏显示时,如果位图比客户区小,则对位图放大;如果位图比客户区大,则对位图缩小。3.支持文件拖放功能。可以从资源管理器中拖动一个位图文件到客户区,就可以显示该位图。程序调试通过后,可以找一个较大的真彩色位图或调整客户区比位图小,在全屏显示方式下,比较使用普通函数与使用视频函数的差别。可以看出,位图放大时两者差别不大,但在位图缩小时,两者差别明显;使用视频函数时位图失真小,显示速度快。还可以从控制面板中将屏幕显示方式从真彩色显示模式切换到256色显示模式,再比较使用普通函数与使用视频函数显示同一个真彩色位图的差&&&&&&&& 别。现在可以体会到使用视频函数的优越性了吧。在全屏显示时,位图的xy方向比例不相同,如要保持相同比例,可在显示程序中加以适当调整即可,读者可自行完成.&&&&&&&&
分享给好友::
All Rights Reserved 图宝贝
本站声明:本站所转载之内容,无任何商业意图,如本网站转载稿件涉及版权、著作权等问题,请您来函与本站管理员取得联系,友情链接请加QQ,要求PR 或者 BR >=2(联系方式:QQ )

我要回帖

更多关于 mfc 加载位图 的文章

 

随机推荐