HMXShapedDialog.cpp
上传用户:yinguanfa
上传日期:2022-02-19
资源大小:400k
文件大小:14k
源码类别:

ListView/ListBox

开发平台:

Visual C++

  1. // HMXShapedDialog.cpp : implementation file
  2. //
  3. /********************************************************************
  4. created: 2001/10/25
  5. file: HMXShapedDialog
  6. author: Massimo Colurcio
  7. homepage: http://www.softhor.com/developmentarea
  8. email: m.colurcio@softhor.com
  9. thanks to:
  10. purpose: free all your creativity...
  11.   
  12. *********************************************************************/
  13. #include "stdafx.h"
  14. #include "HMXShapedDialog.h"
  15. #ifdef _DEBUG
  16. #define new DEBUG_NEW
  17. #undef THIS_FILE
  18. static char THIS_FILE[] = __FILE__;
  19. #endif
  20. /////////////////////////////////////////////////////////////////////////////
  21. // CHMXShapedDialog dialog
  22. CHMXShapedDialog::CHMXShapedDialog()
  23. {
  24. CommonConstruct();
  25. }
  26. CHMXShapedDialog::CHMXShapedDialog(UINT uResource, CWnd* pParent /*=NULL*/)
  27. : CDialog(uResource, pParent)
  28. {
  29. CommonConstruct();
  30. }
  31. CHMXShapedDialog::CHMXShapedDialog(LPCTSTR pszResource, CWnd* pParent /*=NULL*/)
  32. : CDialog(pszResource, pParent)
  33. {
  34. CommonConstruct();
  35. }
  36. void CHMXShapedDialog::CommonConstruct()
  37. {
  38. //
  39. }
  40. void CHMXShapedDialog::DoDataExchange(CDataExchange* pDX)
  41. {
  42. CDialog::DoDataExchange(pDX);
  43. //{{AFX_DATA_MAP(CHMXShapedDialog)
  44. // NOTE: the ClassWizard will add DDX and DDV calls here
  45. //}}AFX_DATA_MAP
  46. }
  47. BEGIN_MESSAGE_MAP(CHMXShapedDialog, CDialog)
  48. //{{AFX_MSG_MAP(CHMXShapedDialog)
  49. ON_WM_CREATE()
  50. ON_WM_PAINT()
  51. ON_WM_MOUSEMOVE()
  52. ON_WM_DESTROY()
  53. //}}AFX_MSG_MAP
  54. END_MESSAGE_MAP()
  55. /////////////////////////////////////////////////////////////////////////////
  56. // CHMXShapedDialog message handlers
  57. /********************************************************************
  58. created: 2001/10/25
  59. in: lpCreateStructure
  60. out: none
  61. return: see CWnd::OnCreate
  62. purpose: overrides this funcion to create the region at
  63. this time. 
  64. Special thanks to David Gallardo Llopis. He wrote
  65. the biggest part of this function
  66. *********************************************************************/
  67. int CHMXShapedDialog::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  68. {
  69. if (CDialog::OnCreate(lpCreateStruct) == -1)
  70. return -1;
  71. // TODO: Add your specialized creation code here
  72. if( m_sFileRgn.IsEmpty() )
  73. return 0;
  74. // The name of the bitmap to load (if not in the same directory as the application, provide full path!)
  75. // If the bitmap is to be load from the resources, the name stands for the ressource-string identification
  76. // If you want to load the bitmap from file 
  77. m_hBmp=(HBITMAP) LoadImage(lpCreateStruct->hInstance,m_sFileRgn,IMAGE_BITMAP,0,0,LR_LOADFROMFILE | LR_CREATEDIBSECTION);
  78. if( !m_hBmp )
  79. return 0;
  80. // If you want to load the bitmap from the resources 
  81. // Uncomment the next line, and comment the previous "LoadImage()" line!
  82. // hImage=(HBITMAP) LoadImage(lpCreateStruct->hInstance,name,IMAGE_BITMAP,0,0,LR_LOADFROMFILE | LR_CREATEDIBSECTION);
  83. // Let's make this function do the hard work. You pass it the handle of the bitmap,
  84. // the color in the bitmap to be transparent, and a third boolean parameter that
  85. // tells the function whether the passed color is to be interpreted as the transparent
  86. // color or as the opaque color
  87. m_hRegion=BitmapRegion( m_hBmp, m_clrTransp, true);
  88. // If there was no problem getting the region, we make it the current clipping region
  89. // of the dialog's window
  90. if(m_hRegion)
  91. SetWindowRgn( m_hRegion, TRUE);
  92. // We ask the bitmap for its size...
  93. GetObject(m_hBmp,sizeof(m_bmInfo),&m_bmInfo);
  94. // At last, we create a display-compatible memory context!
  95. m_hMemDC=CreateCompatibleDC(NULL);
  96. m_hPrevBmp=(HBITMAP)SelectObject(m_hMemDC,m_hBmp);
  97. return 0;
  98. }
  99. void CHMXShapedDialog::OnPaint() 
  100. {
  101. CPaintDC dc(this); // device context for painting
  102. // TODO: Add your message handler code here
  103. BitBlt( dc.m_hDC, 0, 0, m_bmInfo.bmWidth, m_bmInfo.bmHeight, m_hMemDC, 0, 0, SRCCOPY);
  104. // Do not call CDialog::OnPaint() for painting messages
  105. }
  106. /********************************************************************
  107. created: 2001/10/25
  108. in: see CWnd::OnMouseMove
  109. out: see CWnd::OnMouseMove
  110. return: none
  111.   
  112. purpose: use this method to allow window movements dragging
  113. the window clicking the entire client area
  114. *********************************************************************/
  115. void CHMXShapedDialog::OnMouseMove(UINT nFlags, CPoint point) 
  116. {
  117. // TODO: Add your message handler code here and/or call default
  118. // special thanks to Jens Rams <jens_rahm@hotmail.com>
  119. if(nFlags == MK_LBUTTON) {
  120. ReleaseCapture();
  121. SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, 0);
  122. }
  123. CDialog::OnMouseMove(nFlags, point);
  124. }
  125. /********************************************************************
  126. created: 2001/10/25
  127. in: none
  128. out: none
  129. return: none
  130.   
  131. purpose: do a lot of useful stuffs
  132. *********************************************************************/
  133. void CHMXShapedDialog::OnDestroy() 
  134. {
  135. CDialog::OnDestroy();
  136. // TODO: Add your message handler code here
  137. // Simply select the previous bitmap on the memory context...
  138. SelectObject(m_hMemDC, m_hPrevBmp);
  139. // ... and delete the bitmap the we loaded at the beginning
  140. if(m_hBmp) 
  141. DeleteObject(m_hBmp);
  142. }
  143. /********************************************************************
  144. created: 2001/10/25
  145. in: sFileRgn, clrTransp
  146. out:
  147. return: always true
  148.   
  149. purpose: use this method to set dialog shape & image
  150. *********************************************************************/
  151. bool CHMXShapedDialog::SetRegionFile(const CString & sFileRgn, COLORREF clrTransp)
  152. {
  153. m_sFileRgn = sFileRgn;
  154. m_clrTransp = clrTransp;
  155. return true;
  156. }
  157. /********************************************************************
  158. created: 2001/10/25
  159. in: hBitmap, clrTransp, bTransp
  160. out: none
  161. return: region handle
  162. purpose: creates regin from bitmap
  163. *********************************************************************/
  164. HRGN CHMXShapedDialog::BitmapRegion(HBITMAP hBitmap,COLORREF clrTransp, bool bTransp)
  165. {
  166. // We create an empty region
  167. HRGN hRegion = NULL;
  168. // If the passed bitmap is NULL, go away!
  169. if(!hBitmap) 
  170. return hRegion;
  171. // We create a memory context for working with the bitmap
  172. // The memory context is compatible with the display context (screen)
  173. HDC hMemDC=CreateCompatibleDC(NULL);
  174. // If no context is created, go away, too!
  175. if(!hMemDC) 
  176. return hRegion;
  177. // Computation of the bitmap size
  178. BITMAP bmBitmap;
  179. GetObject(hBitmap, sizeof(bmBitmap), &bmBitmap);
  180. // In order to make the space for the region, we
  181. // create a bitmap with 32bit depth color and with the
  182. // size of the loaded bitmap!
  183. BITMAPINFOHEADER RGB32BITSBITMAPINFO=
  184. sizeof(BITMAPINFOHEADER), 
  185. bmBitmap.bmWidth, 
  186. bmBitmap.bmHeight, 
  187. 1,32,BI_RGB,0,0,0,0,0 
  188. };
  189. // Here is the pointer to the bitmap data
  190. VOID *pBits;
  191. // With the previous information, we create the new bitmap!
  192. HBITMAP hNewBitmap;
  193. hNewBitmap=CreateDIBSection(hMemDC,
  194. (BITMAPINFO *)&RGB32BITSBITMAPINFO,
  195. DIB_RGB_COLORS,&pBits,NULL,0);
  196. // If the creation process succeded...
  197. if(hNewBitmap) {
  198. // We select the bitmap onto the created memory context
  199. // and then we store the previosly selected bitmap on this context!
  200. HBITMAP hPrevBmp=(HBITMAP) SelectObject(hMemDC,hNewBitmap);
  201. // We create another device context compatible with the first!
  202. HDC hDC=CreateCompatibleDC(hMemDC);
  203. // If success...
  204. if(hDC) {
  205. // We compute the number of bytes per row that the bitmap contains, rounding to 32 bit-multiples
  206. BITMAP bmNewBitmap;
  207. GetObject(hNewBitmap,sizeof(bmNewBitmap),&bmNewBitmap);
  208. while(bmNewBitmap.bmWidthBytes % 4) 
  209. bmNewBitmap.bmWidthBytes++;
  210. // Copy of the original bitmap on the memory context!
  211. HBITMAP hPrevBmpOrg=(HBITMAP) SelectObject(hDC,hBitmap);
  212. BitBlt(hMemDC,0,0,bmBitmap.bmWidth,bmBitmap.bmHeight,hDC,0,0,SRCCOPY);
  213. // In order to optimize the code, we don't call the GDI each time we
  214. // find a transparent pixel. We use a RGN_DATA structure were we store
  215. // consecutive rectangles, until we have a large amount of them and then we crete
  216. // the composed region with ExtCreateRgn(), combining it with the main region.
  217. // Then we begin again initializing the RGN_DATA structure and doing another
  218. // iteration, until the entire bitmap is analyzed.
  219. // Also, in order to not saturate the Windows API with calls for reserving
  220. // memory, we wait until NUMRECT rectangles are stores in order to claim
  221. // for another NUMRECT memory space!
  222. #define NUMRECT 100
  223. DWORD nMaxRect = NUMRECT;
  224. // We create the memory data
  225. HANDLE hData=GlobalAlloc(GMEM_MOVEABLE,sizeof(RGNDATAHEADER)+(sizeof(RECT)*nMaxRect));
  226. RGNDATA *pData=(RGNDATA*) GlobalLock(hData);
  227. pData->rdh.dwSize=sizeof(RGNDATAHEADER);
  228. pData->rdh.iType=RDH_RECTANGLES;
  229. pData->rdh.nCount=pData->rdh.nRgnSize=0;
  230. SetRect(&pData->rdh.rcBound,MAXLONG,MAXLONG,0,0);
  231. // We study each pixel on the bitmap...
  232. BYTE *pbPixels=(BYTE*) bmNewBitmap.bmBits+(bmNewBitmap.bmHeight-1)*bmNewBitmap.bmWidthBytes;
  233. // Main loop
  234. for(int nRow=0;nRow<bmBitmap.bmHeight;nRow++) 
  235. {
  236. // Horizontal loop
  237. for(int nCol=0;nCol<bmBitmap.bmWidth;nCol++)
  238. {
  239. // We optimized searching for adyacent transparent pixels!
  240. int nXo=nCol;
  241. LONG *plPixel=(LONG*) pbPixels+nCol;
  242. while(nCol<bmBitmap.bmWidth) 
  243. {
  244. bool bInRange=false;
  245. // Massimo wrote:
  246. //
  247. // Could someone explain me why I have to 
  248. // compare colors in that way?????
  249. //
  250. // Blue/Red inversion??????
  251. //
  252. // If the color is that indicated as transparent...
  253. //
  254. /*
  255. This is the original code...
  256. if( GetRValue(*plPixel)==GetRValue(clrTransp) &&
  257. GetGValue(*plPixel)==GetGValue(clrTransp) &&
  258. GetBValue(*plPixel)==GetBValue(clrTransp) )
  259. bInRange=true;
  260. */
  261. if( GetBValue(*plPixel)==GetRValue(clrTransp) &&
  262. GetGValue(*plPixel)==GetGValue(clrTransp) &&
  263. GetRValue(*plPixel)==GetBValue(clrTransp) )
  264. bInRange=true;
  265. if((bTransp) && (bInRange)) 
  266. break;
  267. if((!bTransp) && (!bInRange)) 
  268. break;
  269. plPixel++;
  270. nCol++;
  271. } // while (nCol < bm.bmWidth) 
  272. if(nCol>nXo) 
  273. {
  274. // We add the rectangle (Xo,Row),(Column,Row+1) to the region
  275. // If the number of rectangles is greater then NUMRECT, we claim
  276. // another pack of NUMRECT memory places!
  277. if (pData->rdh.nCount>=nMaxRect)
  278. {
  279. GlobalUnlock(hData);
  280. nMaxRect+=NUMRECT;
  281. hData=GlobalReAlloc(hData,sizeof(RGNDATAHEADER)+(sizeof(RECT)*nMaxRect),GMEM_MOVEABLE);
  282. pData=(RGNDATA *)GlobalLock(hData);
  283. }
  284. RECT *pRect=(RECT*) &pData->Buffer;
  285. SetRect(&pRect[pData->rdh.nCount], nXo, nRow, nCol, nRow+1);
  286. if( nXo<pData->rdh.rcBound.left) 
  287. pData->rdh.rcBound.left=nXo;
  288. if( nRow<pData->rdh.rcBound.top) 
  289. pData->rdh.rcBound.top=nRow;
  290. if(nCol>pData->rdh.rcBound.right) 
  291. pData->rdh.rcBound.right = nCol;
  292. if(nRow+1>pData->rdh.rcBound.bottom) 
  293. pData->rdh.rcBound.bottom=nRow+1;
  294. pData->rdh.nCount++;
  295. // In Win95/08 there is a limitation on the maximum number of
  296. // rectangles a RGN_DATA can store (aprox. 4500), so we call
  297. // the API for a creation and combination with the main region
  298. // each 2000 rectangles. This is a good optimization, because
  299. // instead of calling the routines for combining for each new
  300. // rectangle found, we call them every 2000 rectangles!!!
  301. if(pData->rdh.nCount==2000)
  302. {
  303. HRGN hNewRegion=ExtCreateRegion(NULL,sizeof(RGNDATAHEADER) + (sizeof(RECT) * nMaxRect),pData);
  304. if (hNewRegion) {
  305. // Si ya existe la regi髇 principal,sumamos la nueva,
  306. // si no,entonces de momento la principal coincide con
  307. // la nueva regi髇.
  308. if (hRegion) {
  309. CombineRgn(hRegion,hRegion,hNewRegion,RGN_OR);
  310. DeleteObject(hNewRegion);
  311. } else
  312. hRegion=hNewRegion;
  313. }
  314. // Volvemos a comenzar la suma de rect醤gulos
  315. pData->rdh.nCount=0;
  316. SetRect(&pData->rdh.rcBound,MAXLONG,MAXLONG,0,0);
  317. }
  318. } // if ( nCol > nXo)
  319. } // for (int  nCol ...)
  320. // Nueva Row. Lo del negativo se debe a que el bitmap est