PageRenderTime 43ms CodeModel.GetById 8ms RepoModel.GetById 1ms app.codeStats 0ms

/BotE Game/branch/Alpha7/include/ImageStone/include/FWin32.h

#
C++ Header | 985 lines | 666 code | 93 blank | 226 comment | 96 complexity | e5473add8988889197b2717c91ef67da MD5 | raw file
Possible License(s): GPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-2.0
  1. /*
  2. * Copyright (C) =USTC= Fu Li
  3. *
  4. * Author : Fu Li
  5. * Create : 2005-9-29
  6. * Home : http://www.crazy-bit.com/
  7. * Mail : crazybitwps@hotmail.com
  8. * History :
  9. */
  10. #ifdef WIN32
  11. #ifndef __FOO_WIN32__2005_09_29__H__
  12. #define __FOO_WIN32__2005_09_29__H__
  13. #include "ObjLayer.h"
  14. #include "ObjSelect.h"
  15. #include <shellapi.h>
  16. //=============================================================================
  17. /**
  18. * WIN32 API wrapper.
  19. */
  20. class FCWin32
  21. {
  22. public:
  23. //=============================================================================
  24. /// Test vKey downing now.
  25. static BOOL IsKeyDown (int vKey)
  26. {
  27. assert (vKey!=VK_CAPITAL && vKey!=VK_NUMLOCK && vKey!=VK_SCROLL) ;
  28. return (::GetKeyState(vKey) & 0x8000) ;
  29. }
  30. /// Open URL use default browser.
  31. static void DefaultBrowserURL (LPCTSTR strURL)
  32. {
  33. // test default browser is IE
  34. BOOL bIE = TRUE ;
  35. HKEY hKey = NULL ;
  36. LONG l = ::RegOpenKeyEx (HKEY_CLASSES_ROOT, TEXT("htmlfile\\shell\\open\\command"), 0, KEY_ALL_ACCESS, &hKey) ;
  37. if (l == ERROR_SUCCESS)
  38. {
  39. TCHAR szPath[MAX_PATH] = {0} ;
  40. DWORD dw = sizeof(TCHAR) * MAX_PATH,
  41. dwType = REG_SZ ;
  42. ::RegQueryValueEx (hKey, NULL, NULL, &dwType, (BYTE*)szPath, &dw) ;
  43. ::RegCloseKey (hKey) ;
  44. std::string s = (char*)bstr_t(szPath) ;
  45. bIE = (s.find("iexplore.exe") != std::string::npos) ;
  46. }
  47. if (bIE)
  48. ::ShellExecute (NULL, TEXT("open"), TEXT("iexplore.exe"), strURL, NULL, SW_SHOWNOACTIVATE) ;
  49. else
  50. ::ShellExecute (NULL, TEXT("open"), strURL, NULL, NULL, SW_SHOWNOACTIVATE) ;
  51. }
  52. /**
  53. * @name Character Set convert.
  54. */
  55. //@{
  56. //=============================================================================
  57. /**
  58. * Convert a UTF-8 string to a ASCII string.
  59. */
  60. static std::string UTF8_to_ANSI (const char* szUTF8)
  61. {
  62. if (szUTF8 == NULL)
  63. return "" ;
  64. int nLen = ::MultiByteToWideChar (CP_UTF8, 0, szUTF8, -1, NULL, 0) ;
  65. WCHAR * pWstr = new WCHAR[nLen+1] ;
  66. ZeroMemory (pWstr, sizeof(WCHAR) * (nLen+1)) ;
  67. ::MultiByteToWideChar (CP_UTF8, 0, szUTF8, -1, pWstr, nLen) ;
  68. std::string strAnsi (bstr_t((wchar_t*)pWstr)) ;
  69. delete[] pWstr ;
  70. return strAnsi ;
  71. }
  72. //=============================================================================
  73. /**
  74. * Convert a UTF-8 string to a ASCII string.
  75. */
  76. static std::string ANSI_to_UTF8 (const char* szAnsi)
  77. {
  78. if (szAnsi == NULL)
  79. return "" ;
  80. bstr_t bstrTmp (szAnsi) ;
  81. int nLen = ::WideCharToMultiByte (CP_UTF8, 0, (LPCWSTR)bstrTmp, -1, NULL, 0, NULL, NULL) ;
  82. char * pUTF8 = new char[nLen+1] ;
  83. ZeroMemory (pUTF8, nLen + 1) ;
  84. ::WideCharToMultiByte (CP_UTF8, 0, (LPCWSTR)bstrTmp, -1, pUTF8, nLen, NULL, NULL) ;
  85. std::string strUTF (pUTF8) ;
  86. delete[] pUTF8 ;
  87. return strUTF ;
  88. }
  89. //@}
  90. /**
  91. * @name Autorun at startup of windows.
  92. */
  93. //@{
  94. //=============================================================================
  95. /**
  96. * Get auto run value string.
  97. */
  98. static bstr_t GetAutoRunValue (LPCTSTR szValue)
  99. {
  100. HKEY hKey = NULL ;
  101. bstr_t sK = "Software\\Microsoft\\Windows\\CurrentVersion\\Run" ;
  102. LONG l = ::RegOpenKeyEx (HKEY_CURRENT_USER, sK, 0, KEY_ALL_ACCESS, &hKey) ;
  103. if (l != ERROR_SUCCESS)
  104. {assert(FALSE); return "";}
  105. TCHAR szPath[MAX_PATH] = {0} ;
  106. DWORD dw = sizeof(TCHAR) * MAX_PATH,
  107. dwType = REG_SZ ;
  108. ::RegQueryValueEx (hKey, szValue, NULL, &dwType, (BYTE*)szPath, &dw) ;
  109. ::RegCloseKey (hKey) ;
  110. return szPath ;
  111. }
  112. //=============================================================================
  113. /**
  114. * Set auto run value string.
  115. */
  116. static void SetAutoRunValue (LPCTSTR szValue, LPCTSTR szString)
  117. {
  118. HKEY hKey = NULL ;
  119. bstr_t sK = "Software\\Microsoft\\Windows\\CurrentVersion\\Run" ;
  120. LONG l = ::RegOpenKeyEx (HKEY_CURRENT_USER, sK, 0, KEY_ALL_ACCESS, &hKey) ;
  121. if (l != ERROR_SUCCESS)
  122. {assert(FALSE); return;}
  123. ::RegDeleteValue (hKey, szValue) ;
  124. if (lstrlen(szString))
  125. {
  126. ::RegSetValueEx (hKey, szValue, NULL, REG_SZ, (BYTE*)szString, (lstrlen(szString)+1)*sizeof(TCHAR)) ;
  127. }
  128. ::RegCloseKey (hKey) ;
  129. }
  130. //=============================================================================
  131. /**
  132. * Is autorun enable.
  133. */
  134. static BOOL IsAutoRunEnable (LPCTSTR szValue)
  135. {
  136. return GetAutoRunValue(szValue).length() ? TRUE : FALSE ;
  137. }
  138. //=============================================================================
  139. /**
  140. * Set autorun enable.
  141. */
  142. static void SetAutoRunEnable (LPCTSTR szValue, BOOL bEnable)
  143. {
  144. if (bEnable)
  145. {
  146. TCHAR szPath[MAX_PATH] = {0} ;
  147. ::GetModuleFileName (NULL, szPath, MAX_PATH) ;
  148. SetAutoRunValue (szValue, szPath) ;
  149. }
  150. else
  151. {
  152. SetAutoRunValue (szValue, NULL) ;
  153. }
  154. }
  155. //@}
  156. /**
  157. * @name Window always on top.
  158. */
  159. //@{
  160. //=============================================================================
  161. /**
  162. * Test a window have WS_EX_TOPMOST property.
  163. */
  164. static BOOL IsWindowAlwaysTop (HWND hWnd)
  165. {
  166. return (GetWindowLong(hWnd,GWL_EXSTYLE) & WS_EX_TOPMOST) ;
  167. }
  168. //=============================================================================
  169. /**
  170. * Set/Clear a window's WS_EX_TOPMOST property.
  171. */
  172. static void SetWindowAlwaysTop (HWND hWnd, BOOL bTop)
  173. {
  174. if (!::IsWindow(hWnd) || (::GetDesktopWindow() == hWnd))
  175. return ;
  176. if (bTop)
  177. {
  178. if (!IsWindowAlwaysTop(hWnd))
  179. ::SetWindowPos (hWnd, HWND_TOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE) ;
  180. }
  181. else
  182. {
  183. if (IsWindowAlwaysTop(hWnd))
  184. ::SetWindowPos (hWnd, HWND_NOTOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE) ;
  185. }
  186. }
  187. //@}
  188. /**
  189. * @name Convert between GDI HBITMAP(DDB) and FCObjImage.
  190. */
  191. //@{
  192. //=============================================================================
  193. /**
  194. * Create DDB handle from FCObjImage object.
  195. */
  196. static HBITMAP CreateDDBHandle (const FCObjImage& img)
  197. {
  198. if (!img.IsValidImage())
  199. {/*assert(false);*/ return NULL;}
  200. // prepare info
  201. PCL_array<BITMAPINFOHEADER> bmfh (img.NewImgInfoWithPalette()) ;
  202. HDC hdc = ::GetDC (NULL) ;
  203. HBITMAP hDDB = CreateDIBitmap (hdc, bmfh.get(), CBM_INIT, (VOID*)img.GetMemStart(), (BITMAPINFO*)bmfh.get(), DIB_RGB_COLORS) ;
  204. ::ReleaseDC (NULL, hdc) ;
  205. return hDDB ;
  206. }
  207. //=============================================================================
  208. /**
  209. * Create FCObjImage object from DDB handle.
  210. */
  211. static void CreateImageFromDDB (HBITMAP hBitmap, FCObjImage& img)
  212. {
  213. BITMAP bm ;
  214. ::GetObject (hBitmap, sizeof(BITMAP), &bm) ;
  215. HDC hdc = ::CreateCompatibleDC(NULL) ;
  216. HGDIOBJ hOld = ::SelectObject (hdc, hBitmap) ;
  217. RECT rc = {0, 0, bm.bmWidth, bm.bmHeight} ;
  218. CaptureDC (img, hdc, rc) ;
  219. ::SelectObject (hdc, hOld) ;
  220. ::DeleteDC(hdc) ;
  221. }
  222. //@}
  223. //=============================================================================
  224. /**
  225. * Load FCObjImage object from resource.
  226. */
  227. static void LoadImageRes (FCObjImage& img, LPCTSTR resName, LPCTSTR resType, IMAGE_TYPE imgType, HMODULE hMod=NULL)
  228. {
  229. HRSRC res = ::FindResource (hMod, resName, resType) ;
  230. BYTE * pImgData = (BYTE*)::LockResource (::LoadResource (hMod, res)) ;
  231. if (pImgData)
  232. img.Load (pImgData, ::SizeofResource (hMod, res), imgType) ;
  233. }
  234. //=============================================================================
  235. /**
  236. * Load FCObjImage object from standard Bitmap resource.
  237. */
  238. static void LoadImageBitmapRes (FCObjImage& img, LPCTSTR resName, HMODULE hMod=NULL)
  239. {
  240. HRSRC res = ::FindResource (hMod, resName, RT_BITMAP) ;
  241. BYTE * pImgData = (BYTE*)::LockResource (::LoadResource (hMod, res)) ;
  242. if (pImgData)
  243. img.LoadDIBStream (pImgData, (int)::SizeofResource(hMod, res)) ;
  244. }
  245. /**
  246. * @name Draw image.
  247. */
  248. //@{
  249. //=============================================================================
  250. /**
  251. * Draw entire image to hdc at position (x,y), no scale.
  252. */
  253. static void DrawImage (const FCObjImage& img, HDC hdc, int x, int y)
  254. {
  255. if (!img.IsValidImage())
  256. return ;
  257. // prepare info
  258. PCL_array<BITMAPINFO> bmfh (img.NewImgInfoWithPalette()) ;
  259. // start draw
  260. int nOldMode = ::SetStretchBltMode (hdc, COLORONCOLOR) ;
  261. ::SetDIBitsToDevice (hdc, x, y, img.Width(), img.Height(), 0, 0, 0, img.Height(),
  262. img.GetMemStart(), bmfh.get(), DIB_RGB_COLORS) ;
  263. ::SetStretchBltMode (hdc, nOldMode) ;
  264. }
  265. //=============================================================================
  266. /**
  267. * Draw rcImg of image to rcDrawDC of hdc.
  268. */
  269. static void DrawImage (const FCObjImage& img, HDC hdc, RECT rcDrawDC, RECT rcImg)
  270. {
  271. if (!img.IsValidImage())
  272. return ;
  273. // prepare info
  274. PCL_array<BITMAPINFO> bmfh (img.NewImgInfoWithPalette()) ;
  275. // start draw
  276. int nOldMode = ::SetStretchBltMode (hdc, COLORONCOLOR),
  277. nYStart = img.Height() - (rcImg.top + RECTHEIGHT(rcImg)) ;
  278. ::StretchDIBits (hdc, rcDrawDC.left, rcDrawDC.top, RECTWIDTH(rcDrawDC), RECTHEIGHT(rcDrawDC),
  279. rcImg.left, nYStart, RECTWIDTH(rcImg), RECTHEIGHT(rcImg),
  280. img.GetMemStart(), bmfh.get(), DIB_RGB_COLORS, SRCCOPY) ;
  281. ::SetStretchBltMode (hdc, nOldMode) ;
  282. }
  283. //=============================================================================
  284. /**
  285. * Draw entire image to rcDrawDC of hdc.
  286. */
  287. static void DrawImage (const FCObjImage& img, HDC hdc, RECT rcDrawDC)
  288. {
  289. RECT rcImg = {0, 0, img.Width(), img.Height()} ;
  290. DrawImage (img, hdc, rcDrawDC, rcImg) ;
  291. }
  292. //=============================================================================
  293. /**
  294. * Draw(aspect) entire image to center of rcDrawDC.
  295. */
  296. static void DrawImageAspect (const FCObjImage& img, HDC hdc, RECT rcDrawDC)
  297. {
  298. if (!img.IsValidImage())
  299. return ;
  300. int nNewWidth = img.Width(),
  301. nNewHeight = img.Height() ;
  302. if ((img.Width() > RECTWIDTH(rcDrawDC)) || (img.Height() > RECTHEIGHT(rcDrawDC)))
  303. {
  304. double dx = RECTWIDTH(rcDrawDC) / (double)img.Width(),
  305. dy = RECTHEIGHT(rcDrawDC) / (double)img.Height(),
  306. d = FMin (dx, dy) ;
  307. nNewWidth = FMax (1, (int)(img.Width() * d)) ;
  308. nNewHeight = FMax (1, (int)(img.Height() * d)) ;
  309. }
  310. RECT rcShow = {0, 0, nNewWidth, nNewHeight} ;
  311. ::OffsetRect (&rcShow, (RECTWIDTH(rcDrawDC) - nNewWidth) / 2 + rcDrawDC.left,
  312. (RECTHEIGHT(rcDrawDC) - nNewHeight) / 2 + rcDrawDC.top) ;
  313. assert ((rcShow.left >= 0) && (rcShow.top >= 0)) ;
  314. DrawImage (img, hdc, rcShow) ;
  315. }
  316. //=============================================================================
  317. /**
  318. * AlphaBlend img32 on HDC.
  319. */
  320. static void AlphaImageOnDC (const FCObjImage& img32, HDC hdc, RECT rcOnDC, int nPercent=100)
  321. {
  322. if (!img32.IsValidImage() || (img32.ColorBits() != 32))
  323. return ;
  324. FCObjImage imgDC ;
  325. CaptureDC (imgDC, hdc, rcOnDC) ;
  326. RECT rcImg = {0, 0, img32.Width(), img32.Height()},
  327. rcDCImg = {0, 0, imgDC.Width(), imgDC.Height()} ;
  328. imgDC.AlphaBlend (img32, rcDCImg, rcImg, nPercent) ;
  329. DrawImage (imgDC, hdc, rcOnDC) ;
  330. }
  331. //@}
  332. //=============================================================================
  333. /**
  334. * Capture rcCap of hdc to FCObjImage.
  335. * <B>the received image color format is 24bpp</B>
  336. */
  337. static BOOL CaptureDC (FCObjImage& img, HDC hdc, RECT rcCap)
  338. {
  339. if (IsRectEmpty(&rcCap) || (GetDeviceCaps (hdc, BITSPIXEL) <= 8)) // palette format
  340. {assert(false); return FALSE;}
  341. HDC hMemDC = CreateCompatibleDC (hdc) ;
  342. HBITMAP hDDB = CreateCompatibleBitmap (hdc, RECTWIDTH(rcCap), RECTHEIGHT(rcCap)) ;
  343. if (hDDB == NULL)
  344. {
  345. ::DeleteDC (hMemDC) ;
  346. assert(false); return FALSE;
  347. }
  348. // start capture
  349. HGDIOBJ hOldBmp = ::SelectObject (hMemDC, hDDB) ;
  350. ::BitBlt (hMemDC, 0, 0, RECTWIDTH(rcCap), RECTHEIGHT(rcCap),
  351. hdc, rcCap.left, rcCap.top, SRCCOPY) ;
  352. ::SelectObject (hMemDC, hOldBmp) ;
  353. // attach FCObjImage to DDB
  354. BITMAP bm ;
  355. GetObject (hDDB, sizeof(BITMAP), &bm) ;
  356. if (img.Create (bm.bmWidth, bm.bmHeight, 24))
  357. {
  358. // dest format
  359. PCL_array<BITMAPINFO> bmfh (img.NewImgInfoWithPalette()) ;
  360. ::GetDIBits (hdc, hDDB, 0, bm.bmHeight, img.GetMemStart(), bmfh.get(), DIB_RGB_COLORS) ;
  361. }
  362. DeleteObject (hDDB) ;
  363. DeleteDC (hMemDC) ;
  364. return img.IsValidImage() ;
  365. }
  366. //=============================================================================
  367. /**
  368. * Capture rcCap of screen to FCObjImage.
  369. * <B>the received image color format is 24bpp</B>
  370. */
  371. static BOOL CaptureScreen (FCObjImage& img, RECT rcCap)
  372. {
  373. HDC hSrcDC = ::GetDC (NULL) ;
  374. BOOL bRet = CaptureDC (img, hSrcDC, rcCap) ;
  375. ::ReleaseDC (NULL, hSrcDC) ;
  376. return bRet ;
  377. }
  378. /**
  379. * @name GDI+ helper function.
  380. */
  381. //@{
  382. //=============================================================================
  383. /**
  384. * Create text layer object via GDI+.
  385. */
  386. static void GDIPlus_CreateTextLayer (FCObjTextLayer& layer, PACK_TextLayer tp)
  387. {
  388. // calculate un-addshadow position
  389. const POINT ptOldPos = {layer.GetGraphObjPos().x + layer.m_sizeToOldPos.cx,
  390. layer.GetGraphObjPos().y + layer.m_sizeToOldPos.cy} ;
  391. // --------------------------------------------------- create text image -------
  392. // calc font's Style
  393. INT gpFontStyle = Gdiplus::FontStyleRegular ;
  394. if (tp.m_bBold && tp.m_bItalic) gpFontStyle = Gdiplus::FontStyleBoldItalic ;
  395. else if (tp.m_bBold && !tp.m_bItalic) gpFontStyle = Gdiplus::FontStyleBold ;
  396. else if (!tp.m_bBold && tp.m_bItalic) gpFontStyle = Gdiplus::FontStyleItalic ;
  397. // create GDI+ font
  398. Gdiplus::Font gpFont (&Gdiplus::FontFamily((WCHAR*)bstr_t(tp.m_strFace.c_str())),
  399. (Gdiplus::REAL)tp.m_nFontSize,
  400. gpFontStyle,
  401. Gdiplus::UnitPoint) ;
  402. Gdiplus::TextRenderingHint gpAA = tp.m_bAntiAliased ? Gdiplus::TextRenderingHintAntiAlias : Gdiplus::TextRenderingHintSingleBitPerPixel ;
  403. // calculate string's bound box
  404. const bstr_t strText16 (tp.m_strText.c_str()) ;
  405. Gdiplus::RectF gpBound ;
  406. HDC hdcScreen = CreateCompatibleDC (NULL) ;
  407. {
  408. Gdiplus::Graphics gpGra (hdcScreen) ;
  409. gpGra.SetTextRenderingHint (gpAA) ;
  410. gpGra.MeasureString ((WCHAR*)strText16, -1, &gpFont, Gdiplus::PointF(0,0), &gpBound) ;
  411. gpBound.Width++ ; gpBound.Height++ ; // avoid empty rect
  412. }
  413. DeleteObject(hdcScreen) ;
  414. // create alpha-channel, can't use 8-bit image :-(
  415. Gdiplus::Bitmap imgAlpha ((int)ceil(gpBound.Width), (int)ceil(gpBound.Height), PixelFormat24bppRGB) ;
  416. {
  417. // GDI+ draw string
  418. Gdiplus::Graphics gpGra (&imgAlpha) ;
  419. gpGra.FillRectangle (&Gdiplus::SolidBrush(Gdiplus::Color(0,0,0)), Gdiplus::Rect(0,0,imgAlpha.GetWidth(),imgAlpha.GetHeight())) ;
  420. gpGra.SetTextRenderingHint (gpAA) ;
  421. gpGra.DrawString ((WCHAR*)strText16, -1, &gpFont, Gdiplus::PointF(0,0), &Gdiplus::SolidBrush(Gdiplus::Color(255,255,255))) ;
  422. }
  423. // combine
  424. layer.FCObjImage::Create (imgAlpha.GetWidth(), imgAlpha.GetHeight(), 32) ;
  425. for (int y=0 ; y < layer.Height() ; y++)
  426. for (int x=0 ; x < layer.Width() ; x++)
  427. {
  428. BYTE * p = layer.GetBits(x,y) ;
  429. *(RGBQUAD*)p = tp.m_crFont ; // fill color
  430. Gdiplus::Color cr ;
  431. imgAlpha.GetPixel (x, y, &cr) ;
  432. PCL_A(p) = cr.GetB() ; // append alpha
  433. }
  434. // add shadow to image
  435. if (tp.m_bAddShadow)
  436. {
  437. FCPixelAddShadow aCmd(tp.m_ShadowData) ;
  438. layer.SinglePixelProcessProc (aCmd) ;
  439. }
  440. // --------------------------------------------------- create text image -------
  441. // calculate layer's position
  442. if (tp.m_bAddShadow)
  443. {
  444. RECT rcLayer = {0, 0, layer.Width(), layer.Height()} ;
  445. ::OffsetRect (&rcLayer, ptOldPos.x, ptOldPos.y) ;
  446. RECT rcShadow = rcLayer ;
  447. ::OffsetRect (&rcShadow, tp.m_ShadowData.nOffsetX, tp.m_ShadowData.nOffsetY) ;
  448. ::InflateRect (&rcShadow, tp.m_ShadowData.nSmooth, tp.m_ShadowData.nSmooth) ;
  449. ::UnionRect (&rcShadow, &rcLayer, &rcShadow) ;
  450. layer.SetGraphObjPos (rcShadow.left, rcShadow.top) ;
  451. }
  452. else
  453. layer.SetGraphObjPos (ptOldPos) ;
  454. // can be edit.
  455. layer.m_TxtLayerProp = tp ;
  456. layer.ToolEditFlag() = false ;
  457. // update position offset
  458. layer.m_sizeToOldPos.cx = ptOldPos.x - layer.GetGraphObjPos().x ;
  459. layer.m_sizeToOldPos.cy = ptOldPos.y - layer.GetGraphObjPos().y ;
  460. }
  461. //=============================================================================
  462. /**
  463. * Create GDI+ Bitmap object from an image object.
  464. * you must use <B>delete</B> to delete returned object, high recommended to use std::auto_ptr to wrap returned pointer.
  465. @code
  466. std::auto_ptr<Gdiplus::Bitmap> pBmp (FCWin32::GDIPlus_CreateBitmap(img)) ;
  467. @endcode
  468. * @return return NULL if failed.
  469. */
  470. static Gdiplus::Bitmap* GDIPlus_CreateBitmap (const FCObjImage& img)
  471. {
  472. Gdiplus::PixelFormat fmt ;
  473. switch (img.ColorBits())
  474. {
  475. case 1 : fmt = PixelFormat1bppIndexed ; break;
  476. case 4 : fmt = PixelFormat4bppIndexed ; break;
  477. case 8 : fmt = PixelFormat8bppIndexed ; break;
  478. case 16 :
  479. {
  480. PCL_array<BITMAPINFOHEADER> info (img.NewImgInfoWithPalette()) ;
  481. DWORD * pField = (DWORD*)(info.get() + 1) ;
  482. fmt = (pField[1] == 0x03E0) ? PixelFormat16bppRGB555 : PixelFormat16bppRGB565 ;
  483. }
  484. break ;
  485. case 24 : fmt = PixelFormat24bppRGB ; break;
  486. case 32 : fmt = PixelFormat32bppARGB ; break;
  487. default :
  488. assert(false); return NULL ;
  489. }
  490. Gdiplus::Bitmap * pBmp = new Gdiplus::Bitmap (img.Width(), img.Height(), fmt) ;
  491. // set palette
  492. if (img.ColorBits() <= 8)
  493. {
  494. int nNum = (1<<img.ColorBits()) ;
  495. PCL_array<RGBQUAD> old_pal(nNum) ;
  496. img.GetColorTable (0, nNum, old_pal.get()) ;
  497. Gdiplus::ColorPalette * pPal = (Gdiplus::ColorPalette*)malloc(sizeof(Gdiplus::ColorPalette) + nNum*sizeof(Gdiplus::ARGB)) ;
  498. pPal->Flags = Gdiplus::PaletteFlagsHasAlpha ;
  499. pPal->Count = nNum ;
  500. for (int i=0 ; i < nNum ; i++)
  501. {
  502. RGBQUAD * p = &old_pal[i] ;
  503. pPal->Entries[i] = Gdiplus::Color::MakeARGB (0xFF, PCL_R(p), PCL_G(p), PCL_B(p)) ;
  504. }
  505. pBmp->SetPalette (pPal) ;
  506. free(pPal) ;
  507. }
  508. // set pixel
  509. for (int y=0 ; y < img.Height() ; y++)
  510. {
  511. Gdiplus::Rect rc (0, y, img.Width(), 1) ;
  512. Gdiplus::BitmapData bd ;
  513. bd.Width = img.Width() ;
  514. bd.Height = 1 ;
  515. bd.Stride = img.GetPitch() ;
  516. bd.PixelFormat = fmt ;
  517. bd.Scan0 = img.GetBits(y) ;
  518. bd.Reserved = NULL ;
  519. pBmp->LockBits (&rc, Gdiplus::ImageLockModeWrite|Gdiplus::ImageLockModeUserInputBuf, fmt, &bd) ;
  520. pBmp->UnlockBits (&bd) ;
  521. }
  522. return pBmp ;
  523. }
  524. //=============================================================================
  525. /**
  526. * Create FCObjImage base on Gdiplus::Bitmap.
  527. */
  528. static void GDIPlus_LoadBitmap (Gdiplus::Bitmap& gpBmp, FCObjImage& img)
  529. {
  530. // get image's info
  531. BYTE __bufImgInfo[sizeof(BITMAPINFOHEADER) + 16] = {0} ;
  532. BITMAPINFOHEADER * pInfo = (BITMAPINFOHEADER*)__bufImgInfo ;
  533. DWORD * pMask = (DWORD*)(pInfo + 1) ;
  534. pInfo->biWidth = gpBmp.GetWidth() ;
  535. pInfo->biHeight = gpBmp.GetHeight() ;
  536. pInfo->biCompression = BI_RGB ;
  537. switch (gpBmp.GetPixelFormat())
  538. {
  539. case PixelFormat1bppIndexed : pInfo->biBitCount = 1 ; break ;
  540. case PixelFormat4bppIndexed : pInfo->biBitCount = 4 ; break ;
  541. case PixelFormat8bppIndexed : pInfo->biBitCount = 8 ; break ;
  542. case PixelFormat16bppRGB555 :
  543. case PixelFormat16bppARGB1555 :
  544. pInfo->biBitCount = 16 ;
  545. pInfo->biCompression = BI_BITFIELDS ;
  546. pMask[0] = FCObjImage::MASK16_RED_555 ;
  547. pMask[1] = FCObjImage::MASK16_GREEN_555 ;
  548. pMask[2] = FCObjImage::MASK16_BLUE_555 ;
  549. break ;
  550. case PixelFormat16bppRGB565 :
  551. pInfo->biBitCount = 16 ;
  552. pInfo->biCompression = BI_BITFIELDS ;
  553. pMask[0] = FCObjImage::MASK16_RED_565 ;
  554. pMask[1] = FCObjImage::MASK16_GREEN_565 ;
  555. pMask[2] = FCObjImage::MASK16_BLUE_565 ;
  556. break ;
  557. case PixelFormat24bppRGB : pInfo->biBitCount = 24 ; break ;
  558. case PixelFormat32bppRGB :
  559. case PixelFormat32bppPARGB :
  560. case PixelFormat32bppARGB : pInfo->biBitCount = 32 ; break ;
  561. default :
  562. return ;
  563. }
  564. // create image
  565. if (!img.Create(pInfo))
  566. return ;
  567. // get palette
  568. if (img.ColorBits() <= 8)
  569. {
  570. int nByte = gpBmp.GetPaletteSize() ;
  571. PCL_array<Gdiplus::ColorPalette> pPal (new BYTE[nByte]) ;
  572. gpBmp.GetPalette (pPal.get(), nByte) ;
  573. PCL_array<RGBQUAD> fp (pPal.get()->Count) ;
  574. for (UINT i=0 ; i < pPal.get()->Count ; i++)
  575. {
  576. Gdiplus::Color c (pPal.get()->Entries[i]) ;
  577. fp[i] = PCL_RGBA (c.GetR(), c.GetG(), c.GetB(), c.GetA()) ;
  578. }
  579. img.SetColorTable (0, pPal.get()->Count, fp.get()) ;
  580. }
  581. // get pixel
  582. for (int y=0 ; y < img.Height() ; y++)
  583. {
  584. Gdiplus::Rect rc (0, y, img.Width(), 1) ;
  585. Gdiplus::BitmapData bd ;
  586. bd.Width = img.Width() ;
  587. bd.Height = 1 ;
  588. bd.Stride = img.GetPitch() ;
  589. bd.PixelFormat = gpBmp.GetPixelFormat() ;
  590. bd.Scan0 = img.GetBits(y) ;
  591. bd.Reserved = NULL ;
  592. gpBmp.LockBits (&rc, Gdiplus::ImageLockModeRead|Gdiplus::ImageLockModeUserInputBuf, gpBmp.GetPixelFormat(), &bd) ;
  593. gpBmp.UnlockBits (&bd) ;
  594. }
  595. // if 32bpp image no alpha channel, we fill 0xFF
  596. if (gpBmp.GetPixelFormat() == PixelFormat32bppRGB)
  597. img.SetAlphaChannelValue(0xFF) ;
  598. }
  599. //=============================================================================
  600. /**
  601. * Resize image using GDI+ (image >= 16bpp).
  602. */
  603. static void GDIPlus_ResizeImage (FCObjImage& img, int nNewWidth, int nNewHeight, Gdiplus::InterpolationMode mode = Gdiplus::InterpolationModeHighQualityBicubic)
  604. {
  605. if (!img.IsValidImage() || (nNewWidth < 1) || (nNewHeight < 1) || (img.ColorBits() < 16))
  606. return ;
  607. // backup old size
  608. int nOldWidth = img.Width(),
  609. nOldHeight = img.Height() ;
  610. // GDI+ border blur error when 32bpp ? :-(
  611. img.ExpandFrame (true, 10, 10, 10, 10) ;
  612. std::auto_ptr<Gdiplus::Bitmap> old_bmp (FCWin32::GDIPlus_CreateBitmap(img)) ;
  613. Gdiplus::Bitmap new_bmp (nNewWidth, nNewHeight, old_bmp->GetPixelFormat()) ;
  614. {
  615. Gdiplus::Graphics gpGra (&new_bmp) ;
  616. gpGra.SetInterpolationMode (mode) ;
  617. Gdiplus::Rect rc (0, 0, nNewWidth, nNewHeight) ;
  618. gpGra.DrawImage (old_bmp.get(), rc, 10, 10, nOldWidth, nOldHeight, Gdiplus::UnitPixel, NULL, NULL, NULL) ;
  619. }
  620. FCWin32::GDIPlus_LoadBitmap (new_bmp, img) ;
  621. }
  622. //@}
  623. //=============================================================================
  624. /**
  625. * Draw selection object.
  626. * HDC's origin must have been located at top-left of canvas. <BR>
  627. * this function calculate edge point by canvas's zoom scale
  628. * @param rcCanvas : RECT of visible canvas, it's actual coordinate.
  629. */
  630. static void DrawSelection (HDC hdc, FCObjSelect& sel, const PCL_Interface_ZoomScale& canvas, RECT rcCanvas)
  631. {
  632. static const BYTE s_ant_data[8][8] =
  633. {
  634. {
  635. 0xF0, /* ####---- */
  636. 0xE1, /* ###----# */
  637. 0xC3, /* ##----## */
  638. 0x87, /* #----### */
  639. 0x0F, /* ----#### */
  640. 0x1E, /* ---####- */
  641. 0x3C, /* --####-- */
  642. 0x78, /* -####--- */
  643. },
  644. {
  645. 0xE1, /* ###----# */
  646. 0xC3, /* ##----## */
  647. 0x87, /* #----### */
  648. 0x0F, /* ----#### */
  649. 0x1E, /* ---####- */
  650. 0x3C, /* --####-- */
  651. 0x78, /* -####--- */
  652. 0xF0, /* ####---- */
  653. },
  654. {
  655. 0xC3, /* ##----## */
  656. 0x87, /* #----### */
  657. 0x0F, /* ----#### */
  658. 0x1E, /* ---####- */
  659. 0x3C, /* --####-- */
  660. 0x78, /* -####--- */
  661. 0xF0, /* ####---- */
  662. 0xE1, /* ###----# */
  663. },
  664. {
  665. 0x87, /* #----### */
  666. 0x0F, /* ----#### */
  667. 0x1E, /* ---####- */
  668. 0x3C, /* --####-- */
  669. 0x78, /* -####--- */
  670. 0xF0, /* ####---- */
  671. 0xE1, /* ###----# */
  672. 0xC3, /* ##----## */
  673. },
  674. {
  675. 0x0F, /* ----#### */
  676. 0x1E, /* ---####- */
  677. 0x3C, /* --####-- */
  678. 0x78, /* -####--- */
  679. 0xF0, /* ####---- */
  680. 0xE1, /* ###----# */
  681. 0xC3, /* ##----## */
  682. 0x87, /* #----### */
  683. },
  684. {
  685. 0x1E, /* ---####- */
  686. 0x3C, /* --####-- */
  687. 0x78, /* -####--- */
  688. 0xF0, /* ####---- */
  689. 0xE1, /* ###----# */
  690. 0xC3, /* ##----## */
  691. 0x87, /* #----### */
  692. 0x0F, /* ----#### */
  693. },
  694. {
  695. 0x3C, /* --####-- */
  696. 0x78, /* -####--- */
  697. 0xF0, /* ####---- */
  698. 0xE1, /* ###----# */
  699. 0xC3, /* ##----## */
  700. 0x87, /* #----### */
  701. 0x0F, /* ----#### */
  702. 0x1E, /* ---####- */
  703. },
  704. {
  705. 0x78, /* -####--- */
  706. 0xF0, /* ####---- */
  707. 0xE1, /* ###----# */
  708. 0xC3, /* ##----## */
  709. 0x87, /* #----### */
  710. 0x0F, /* ----#### */
  711. 0x1E, /* ---####- */
  712. 0x3C, /* --####-- */
  713. },
  714. };
  715. static const BYTE s_ant_xmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01} ;
  716. // calculate edge points
  717. sel.RecalculateEdge (canvas.GetZoomScale(), false) ;
  718. // ==> scaled coordinate
  719. canvas.Actual_to_Scaled (rcCanvas) ;
  720. rcCanvas.right++ ; rcCanvas.bottom++ ; // ...division, float
  721. // selection object's position
  722. POINT ptPos = sel.GetGraphObjPos() ;
  723. canvas.Actual_to_Scaled (ptPos) ;
  724. sel.m_nCurAnt = ++sel.m_nCurAnt % 8 ;
  725. for (size_t i=0 ; i < sel.m_ptEdge.size() ; i++)
  726. {
  727. POINT ptDraw = {ptPos.x + sel.m_ptEdge[i].x, ptPos.y + sel.m_ptEdge[i].y} ;
  728. if (!::PtInRect(&rcCanvas, ptDraw))
  729. continue ;
  730. COLORREF crFill ;
  731. if (s_ant_data[sel.m_nCurAnt][sel.m_ptEdge[i].y % 8] & s_ant_xmask[sel.m_ptEdge[i].x % 8])
  732. crFill = RGB(255,255,255) ;
  733. else
  734. crFill = RGB(0,0,0) ;
  735. ::SetPixel (hdc, ptDraw.x, ptDraw.y, crFill) ;
  736. }
  737. }
  738. //=============================================================================
  739. /**
  740. * Create HRGN object from a 32bpp image.
  741. * alpha=0 means outter of region.
  742. */
  743. static HRGN ConvertAlphaImageToHRGN (const FCObjImage& img32)
  744. {
  745. if (!img32.IsValidImage() || (img32.ColorBits() != 32))
  746. {assert(false); return NULL;}
  747. HRGN hRgn = ::CreateRectRgn (0, 0, img32.Width(), img32.Height()) ;
  748. for (int y=0 ; y < img32.Height() ; y++)
  749. {
  750. int nLastX = 0 ;
  751. BOOL bStartCount = FALSE ;
  752. for (int x=0 ; x < img32.Width() ; x++)
  753. {
  754. if (PCL_A(img32.GetBits (x,y)))
  755. {
  756. if (bStartCount)
  757. {
  758. // erase rect
  759. HRGN hSingle = ::CreateRectRgn (nLastX, y, x, y+1) ;
  760. ::CombineRgn (hRgn, hRgn, hSingle, RGN_DIFF) ;
  761. ::DeleteObject (hSingle) ;
  762. bStartCount = FALSE ;
  763. }
  764. }
  765. else
  766. {
  767. if (!bStartCount)
  768. {
  769. bStartCount = TRUE ;
  770. nLastX = x ;
  771. }
  772. }
  773. }
  774. if (bStartCount)
  775. {
  776. // erase rect
  777. HRGN hSingle = ::CreateRectRgn (nLastX, y, img32.Width(), y+1) ;
  778. ::CombineRgn (hRgn, hRgn, hSingle, RGN_DIFF) ;
  779. ::DeleteObject (hSingle) ;
  780. }
  781. }
  782. return hRgn ;
  783. }
  784. /**
  785. * @name Clipboard.
  786. */
  787. //@{
  788. //=============================================================================
  789. /**
  790. * Whether current clipboard has a bitmap (DIB).
  791. */
  792. static bool IsPasteAvailable()
  793. {
  794. return ::IsClipboardFormatAvailable(CF_DIB) ? true : false ;
  795. }
  796. //=============================================================================
  797. /**
  798. * Copy img to clipboard (the image must >= 24bpp).
  799. */
  800. static void CopyToClipboard (const FCObjImage& img)
  801. {
  802. if (img.IsValidImage() && (img.ColorBits() >= 24))
  803. if (::OpenClipboard (NULL))
  804. {
  805. // create HGLOBAL
  806. HGLOBAL hMem = GlobalAlloc (GMEM_MOVEABLE, img.GetPitch()*img.Height() + sizeof(BITMAPINFOHEADER) + 16) ;
  807. BYTE * pClipData = (BYTE*)GlobalLock(hMem) ;
  808. // fill image's info
  809. PCL_array<BYTE> imgInfo (img.NewImgInfoWithPalette()) ;
  810. CopyMemory (pClipData, imgInfo.get(), sizeof(BITMAPINFOHEADER)) ;
  811. pClipData += sizeof(BITMAPINFOHEADER) ;
  812. CopyMemory (pClipData, img.GetMemStart(), img.GetPitch()*img.Height()) ;
  813. GlobalUnlock (hMem) ;
  814. if (::EmptyClipboard())
  815. ::SetClipboardData (CF_DIB, hMem) ;
  816. else
  817. {
  818. assert(false);
  819. GlobalFree (hMem) ;
  820. }
  821. ::CloseClipboard() ;
  822. // GlobalFree (hMem) ; // it is a nightmare :-(
  823. }
  824. }
  825. //=============================================================================
  826. /**
  827. * Get clipboard's image (the returned image is 32bpp).
  828. */
  829. static void GetClipboardImage (FCObjImage& img)
  830. {
  831. if (IsPasteAvailable())
  832. if (::OpenClipboard (NULL))
  833. {
  834. // get bitmap
  835. BITMAPINFOHEADER * bmif = (BITMAPINFOHEADER*)::GetClipboardData(CF_DIB) ;
  836. if (img.Create (bmif))
  837. {
  838. // palette
  839. BYTE * pCurr = ((BYTE*)bmif) + bmif->biSize ;
  840. if (img.ColorBits() <= 8)
  841. {
  842. int nCount = 1 << img.ColorBits() ;
  843. img.SetColorTable (0, nCount, (RGBQUAD*)pCurr) ;
  844. pCurr += (4 * nCount) ;
  845. }
  846. else if ((bmif->biCompression == BI_BITFIELDS) && (bmif->biSize == sizeof(BITMAPINFOHEADER)))
  847. pCurr += 12 ;
  848. // copy pixel
  849. CopyMemory (img.GetMemStart(), pCurr, img.GetPitch()*img.Height()) ;
  850. if (img.ColorBits() == 32)
  851. {
  852. if (bmif->biCompression == BI_BITFIELDS)
  853. img.SetAlphaChannelValue (0xFF) ;
  854. }
  855. else
  856. img.ConvertTo32Bit() ;
  857. }
  858. ::CloseClipboard() ;
  859. }
  860. }
  861. //@}
  862. //=============================================================================
  863. /**
  864. * Get a temp file path.
  865. */
  866. static bstr_t QueryTempFilePath()
  867. {
  868. TCHAR szTmpPath[MAX_PATH],
  869. szFilename[MAX_PATH] ;
  870. ::GetTempPath (MAX_PATH, szTmpPath) ;
  871. ::GetTempFileName (szTmpPath, bstr_t("foo"), 0, szFilename) ;
  872. return szFilename ;
  873. }
  874. //=============================================================================
  875. /**
  876. * Get module path.
  877. */
  878. static bstr_t GetModulePath (HMODULE hModule=NULL)
  879. {
  880. TCHAR szApp[MAX_PATH],
  881. szDriver[_MAX_DRIVE],
  882. szPath[MAX_PATH] ;
  883. ::GetModuleFileName (hModule, szApp, MAX_PATH) ;
  884. //::_tsplitpath (szApp, szDriver, szPath, NULL, NULL) ;
  885. ::_tsplitpath_s (szApp, szDriver, sizeof (szDriver), szPath, sizeof (szPath), NULL, NULL, NULL, NULL) ;
  886. //::_tmakepath (szApp, szDriver, szPath, NULL, NULL) ;
  887. ::_tmakepath_s (szApp, sizeof(szApp), szDriver, szPath, NULL, NULL);
  888. return szApp ;
  889. }
  890. };
  891. #endif // __FOO_WIN32__2005_09_29__H__
  892. #endif// WIN32