//-------------------------------------------------------------------------- // Clipper.cpp : test out theme drawing and fast clipping //-------------------------------------------------------------------------- #include "stdafx.h" #include "resource.h" #define ASSERT(x) #include "uxthemep.h" #include "tmschema.h" #include "borderfill.h" #include "imagefile.h" #include "textdraw.h" #include "stdlib.h" #include "stdio.h" #include "autos.h" //-------------------------------------------------------------------------- #define RECTWIDTH(rc) (rc.right - rc.left) #define RECTHEIGHT(rc) (rc.bottom - rc.top) #define CLIPPER_FONTHEIGHT 55 //-------------------------------------------------------------------------- HINSTANCE hInst; HWND hwndMain; HWND hwndTab; HWND hwndDisplay; TCHAR *pszMainWindowClass = L"Clipper"; TCHAR *pszDisplayWindowClass = L"ClipperDisplay"; //----------------------------------------------------------------------------------- enum IMAGEFILEDRAW { IF_REG, IF_TRANS, IF_ALPHA }; //----------------------------------------------------------------------------------- LPCWSTR szPageNames[] = { L"BorderFill", L"BorderFill-R", L"ImageFile", L"ImageFile-R", L"Glyph", L"Glyph-R", L"MultiImage", L"MultiImage-R", L"Text", L"Text-R", L"Borders", L"Borders-R", L"SourceSizing", L"SourceSizing-R", }; //----------------------------------------------------------------------------------- enum GROUPID { GID_BORDERFILL, GID_IMAGEFILE, GID_GLYPH, GID_MULTIIMAGE, GID_TEXT, GID_BORDERS, GID_SRCSIZING, }; //----------------------------------------------------------------------------------- #define MAXGROUPS ((ARRAYSIZE(szPageNames))/2) #define MAXTESTITEMS 50 //----------------------------------------------------------------------------------- // Foward declarations of functions included in this code module: BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK DisplayWndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); void CreateDrawObjects(); BOOL CreateAllWindows(); void RegisterWindowClasses(); //----------------------------------------------------------------------------------- HRESULT MakeErrorLast() {return E_FAIL;} //----------------------------------------------------------------------------------- BOOL CaptureBitmaps(); BOOL WriteBitmapToFile(BITMAPINFOHEADER *pHdr, BYTE *pBits, LPCWSTR pszBaseName); BOOL WriteBitmapHeader(HANDLE hOutFile, BYTE *pMemoryHdr, DWORD dwTotalPixelBytes); void OnDisplayResize(); void PaintObjects(HDC hdc, RECT *prc, int iGroupId); //----------------------------------------------------------------------------------- SIZE szCell = {100, 60}; RECT rcDraw = {10, 10, 50, 45}; // where to draw within cell //----------------------------------------------------------------------------------- struct TESTITEM { HTHEME hTheme; DWORD dwDtbFlags; WCHAR szName[MAX_PATH]; }; //----------------------------------------------------------------------------------- //---- scrolling support ---- int iVertOffset = 0; int iMaxVertOffset = 0; // set by WM_SIZE int iVertLineSize = 10; // # of pixels int iVertPageSize = 0; // set by WM_SIZE //----------------------------------------------------------------------------------- int iItemCount[MAXGROUPS] = {0}; TESTITEM TestItems[MAXGROUPS][MAXTESTITEMS]; BOOL fCapturing = FALSE; //----------------------------------------------------------------------------------- int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int nCmdShow) { MSG msg; HACCEL hAccelTable; hInst = hInstance; RegisterWindowClasses(); InitCommonControlsEx(NULL); if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } //---- parse cmdline params ---- USES_CONVERSION; LPCSTR p = W2A(lpCmdLine); while (*p) { while (isspace(*p)) p++; //---- parse switches ---- if ((*p == '/') || (*p == '-')) { p++; if ((*p == 'c') || (*p == 'C')) { p++; fCapturing = TRUE; } } } hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_CLIPPER); if (fCapturing) { CaptureBitmaps(); return 0; } // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return static_cast(msg.wParam); } //-------------------------------------------------------------------------- BOOL CaptureBitmaps() { //---- paint each tab page to a memory dc & convert to a bitmap file ---- HDC hdcClient = GetDC(NULL); RECT rt = {0, 0, 800, 600}; // currently captures all good info BITMAPINFOHEADER BitMapHdr = {sizeof(BITMAPINFOHEADER), WIDTH(rt), HEIGHT(rt), 1, 24, BI_RGB}; //---- create a DIB to paint into ---- BYTE *pBits; HBITMAP hBitmap = CreateDIBSection(hdcClient, (BITMAPINFO *)&BitMapHdr, DIB_RGB_COLORS, (void **)&pBits, NULL, 0); HDC hdcMemory = CreateCompatibleDC(hdcClient); HBITMAP hOldBitmap = (HBITMAP)SelectObject(hdcMemory, hBitmap); //---- for each tab that we can draw ---- for (int iTabNum=0; iTabNum < ARRAYSIZE(szPageNames); iTabNum++) { iVertOffset = 0; iVertPageSize = RECTHEIGHT(rt); int iGroupId = iTabNum/2; //---- keep tester interested by sync. visuals ---- TabCtrl_SetCurSel(hwndTab, iTabNum); OnDisplayResize(); iVertPageSize = RECTHEIGHT(rt); InvalidateRect(hwndDisplay, NULL, TRUE); if (iTabNum % 2) // if its a mirrored page SetLayout(hdcMemory, LAYOUT_RTL); else SetLayout(hdcMemory, 0); //---- clear the background first ---- HBRUSH hbr = CreateSolidBrush(RGB(255, 255, 255)); FillRect(hdcMemory, &rt, hbr); //---- draw the objects/labels for this tab ---- PaintObjects(hdcMemory, &rt, iGroupId); //---- now copy DIB bits to a bitmap file ---- WriteBitmapToFile(&BitMapHdr, pBits, szPageNames[iTabNum]); } //---- clean up ---- SelectObject(hdcMemory, hOldBitmap); DeleteDC(hdcMemory); DeleteObject(hBitmap); ReleaseDC(NULL, hdcClient); return TRUE; } //-------------------------------------------------------------------------- BOOL WriteBitmapToFile(BITMAPINFOHEADER *pHdr, BYTE *pBits, LPCWSTR pszBaseName) { BOOL fWroteFile = FALSE; //---- get size of bitmap ---- int iDibWidth = pHdr->biWidth; int iDibHeight = pHdr->biHeight; int iRawBytes = iDibWidth * 3; int iBytesPerRow = 4*((iRawBytes+3)/4); int iPixelBytesTotal = iBytesPerRow * iDibHeight; //---- create the bitmap file ---- WCHAR szName[MAX_PATH]; wsprintf(szName, L"%s.bmp", pszBaseName); HANDLE hFileOutput = CreateFile(szName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); if (hFileOutput == INVALID_HANDLE_VALUE) { printf("\nError - could not open bitmap file for output: %s\n", szName); goto exit; } //---- write the bitmap FILE header ---- if (! WriteBitmapHeader(hFileOutput, (BYTE *)pHdr, iPixelBytesTotal)) goto exit; //---- write the bitmap MEMORY header ---- DWORD dw; if (! WriteFile(hFileOutput, pHdr, sizeof(*pHdr), &dw, NULL)) goto exit; //---- write the bitmap bits ---- if (! WriteFile(hFileOutput, pBits, iPixelBytesTotal, &dw, NULL)) goto exit; //---- close the file ---- CloseHandle(hFileOutput); fWroteFile = TRUE; exit: return fWroteFile; } //--------------------------------------------------------------------------- BOOL WriteBitmapHeader(HANDLE hOutFile, BYTE *pMemoryHdr, DWORD dwTotalPixelBytes) { BOOL fOK = FALSE; BYTE pbHdr1[] = {0x42, 0x4d}; BYTE pbHdr2[] = {0x0, 0x0, 0x0, 0x0}; int iFileLen; DWORD dw; //---- add bitmap hdr at front ---- HRESULT hr = WriteFile(hOutFile, pbHdr1, sizeof(pbHdr1), &dw, NULL); if (FAILED(hr)) goto exit; //---- add length of data ---- iFileLen = dwTotalPixelBytes + sizeof(BITMAPFILEHEADER); hr = WriteFile(hOutFile, &iFileLen, sizeof(int), &dw, NULL); if (FAILED(hr)) goto exit; hr = WriteFile(hOutFile, pbHdr2, sizeof(pbHdr2), &dw, NULL); if (FAILED(hr)) goto exit; //---- offset to bits (who's idea was *this* field?) ---- int iOffset, iColorTableSize; DWORD dwSize; iOffset = sizeof(BITMAPFILEHEADER); dwSize = *(DWORD *)pMemoryHdr; iOffset += dwSize; iColorTableSize = 0; switch (dwSize) { case sizeof(BITMAPCOREHEADER): BITMAPCOREHEADER *hdr1; hdr1 = (BITMAPCOREHEADER *)pMemoryHdr; if (hdr1->bcBitCount == 1) iColorTableSize = 2*sizeof(RGBTRIPLE); else if (hdr1->bcBitCount == 4) iColorTableSize = 16*sizeof(RGBTRIPLE); else if (hdr1->bcBitCount == 8) iColorTableSize = 256*sizeof(RGBTRIPLE); break; case sizeof(BITMAPINFOHEADER): case sizeof(BITMAPV4HEADER): case sizeof(BITMAPV5HEADER): BITMAPINFOHEADER *hdr2; hdr2 = (BITMAPINFOHEADER *)pMemoryHdr; if (hdr2->biClrUsed) iColorTableSize = hdr2->biClrUsed*sizeof(RGBQUAD); else { if (hdr2->biBitCount == 1) iColorTableSize = 2*sizeof(RGBQUAD); else if (hdr2->biBitCount == 4) iColorTableSize = 16*sizeof(RGBQUAD); else if (hdr2->biBitCount == 8) iColorTableSize = 256*sizeof(RGBQUAD); } break; } iOffset += iColorTableSize; hr = WriteFile(hOutFile, &iOffset, sizeof(int), &dw, NULL); if (FAILED(hr)) goto exit; fOK = TRUE; exit: return fOK; } //-------------------------------------------------------------------------- void DrawTargetRect(HDC hdc, RECT *prc, COLORREF cr) { //---- draw purple target dashed rect ---- //---- prepare drawing objects ---- HPEN hPen = CreatePen(PS_DOT, 1, cr); HPEN hOldPen = (HPEN)SelectObject(hdc, hPen); HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(NULL_BRUSH)); //---- draw that thing ---- Rectangle(hdc, prc->left-1, prc->top-1, prc->right+1, prc->bottom+1); //---- restore DC ---- SelectObject(hdc, hOldPen); SelectObject(hdc, hOldBrush); DeleteObject(hPen); } //-------------------------------------------------------------------------- void DrawClip(HTHEME hTheme, HDC hdc, RECT *prc, int iRowIndex, int iColIndex, DWORD dwDtbFlags) { RECT rect, rcClip; int left = prc->left + (iColIndex+1)*szCell.cx; int top = prc->top + (iRowIndex+1)*szCell.cy; HRESULT hr = S_OK; SetRect(&rect, left + rcDraw.left, top + rcDraw.top, left + rcDraw.right, top + rcDraw.bottom); //---- draw purple target dashed rect ---- DrawTargetRect(hdc, &rect, RGB(128, 128, 255)); switch (iColIndex) // clipping type { case 0: // no clipping break; case 1: // over clipping rcClip = rect; rcClip.left -= 4; rcClip.right += 4; rcClip.top -= 4; rcClip.bottom += 4; break; case 2: // exact clipping rcClip = rect; break; case 3: // partial overlap rcClip = rect; rcClip.left += 8; rcClip.right -= 8; rcClip.top += 8; rcClip.bottom -= 8; break; case 4: // InOut1 rcClip = rect; rcClip.left -= 3; rcClip.right = rcClip.left + 20; rcClip.top -= 3; rcClip.bottom = rcClip.top + 20; break; case 5: // InOut2 rcClip = rect; rcClip.left += 20; rcClip.right += 5; rcClip.top += 15;; rcClip.bottom += 5; break; case 6: // out clip rcClip.left = rect.right + 6; rcClip.right = rcClip.left + 9; rcClip.top = rect.top - 2; rcClip.bottom = rect.bottom + 2; break; } //---- draw red clipping rect ---- if (iColIndex) { HPEN hPen = CreatePen(PS_DOT, 1, RGB(255, 0, 0)); HPEN hOldPen = (HPEN)SelectObject(hdc, hPen); HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, GetStockObject(NULL_BRUSH)); Rectangle(hdc, rcClip.left-1, rcClip.top-1, rcClip.right+1, rcClip.bottom+1); SelectObject(hdc, hOldPen); SelectObject(hdc, hOldBrush); DeleteObject(hPen); } DTBGOPTS DtbOpts = {sizeof(DtbOpts)}; DtbOpts.dwFlags = dwDtbFlags; if (iColIndex) // pass clipping rect { DtbOpts.dwFlags |= DTBG_CLIPRECT; DtbOpts.rcClip = rcClip; } hr = DrawThemeBackgroundEx(hTheme, hdc, 1, 2, &rect, &DtbOpts); if (FAILED(hr)) { WCHAR buff[100]; wsprintf(buff, L"DrawThemeBackgroundEx err: hr=0x%x, irow=%d, icol=%d", hr, iRowIndex, iColIndex); //MessageBox(NULL, buff, L"Error", MB_OK); } } //-------------------------------------------------------------------------- void DrawTextObjects(HTHEME hTheme, HDC hdc, RECT *prc, int iRowIndex, LPCWSTR pszName) { int left = prc->left + 4; // some padding away from edge int top = prc->top + iRowIndex*szCell.cy + 18; // try to center //---- draw label in left cell ---- TextOut(hdc, left, top, pszName, wcslen(pszName)); left += szCell.cx; RECT rc = {left, top, left+szCell.cx*5, top+szCell.cy}; //---- draw actual test text ---- HRESULT hr = DrawThemeText(hTheme, hdc, 1, 2, L"Testing Text Drawing", -1, 0, 0, &rc); if (FAILED(hr)) { WCHAR buff[100]; wsprintf(buff, L"DrawThemeText err: hr=0x%x, irow=%d", hr, iRowIndex); MessageBox(NULL, buff, L"Error", MB_OK); } } //-------------------------------------------------------------------------- void DrawClips(HTHEME hTheme, HDC hdc, RECT *prc, int iRowIndex, LPCWSTR pszName, DWORD dwDtbFlags) { //---- label object on left ---- int left = prc->left + 4; // some padding away from edge int top = prc->top + (iRowIndex+1)*szCell.cy + 18; // try to center //---- manual page clipping ---- if ((top + szCell.cy) < 0) return; if (top > iVertPageSize) return; TextOut(hdc, left, top, pszName, wcslen(pszName)); //---- draw clipping variations ---- for (int i=0; i <= 6; i++) { DrawClip(hTheme, hdc, prc, iRowIndex, i, dwDtbFlags); } } //-------------------------------------------------------------------------- void AddItem(CDrawBase *pObject, CTextDraw *pTextObj, LPCWSTR pszName, int iGroupId, DWORD dwOtdFlags=0, DWORD dwDtbFlags=0) { HTHEME hTheme = NULL; if (iItemCount[iGroupId] >= MAXTESTITEMS) return; if (pObject) { if (pObject->_eBgType == BT_BORDERFILL) { CBorderFill *pTo = new CBorderFill; if (pTo) { memcpy(pTo, pObject, sizeof(CBorderFill)); hTheme = CreateThemeDataFromObjects(pTo, NULL, dwOtdFlags); } } else // imagefile { CMaxImageFile *pFrom = (CMaxImageFile *)pObject; CMaxImageFile *pTo = new CMaxImageFile; if (pTo) { //---- transfer CImageFile object & variable number of DIBINFO's ---- DWORD dwLen = sizeof(CImageFile) + sizeof(DIBINFO)*pFrom->_iMultiImageCount; memcpy(pTo, pFrom, dwLen); hTheme = CreateThemeDataFromObjects(pTo, NULL, dwOtdFlags); } } } else // text object { CTextDraw *pTo = new CTextDraw; if (pTo) { memcpy(pTo, pTextObj, sizeof(CTextDraw)); hTheme = CreateThemeDataFromObjects(NULL, pTo, dwOtdFlags); } } if (hTheme) { int iIndex = iItemCount[iGroupId]; TestItems[iGroupId][iIndex].hTheme = hTheme; TestItems[iGroupId][iIndex].dwDtbFlags = dwDtbFlags; lstrcpy(TestItems[iGroupId][iIndex].szName, pszName); iItemCount[iGroupId]++; } else { MessageBox(NULL, L"Error creating hTheme from obj", L"Error", MB_OK); } } //-------------------------------------------------------------------------- void CreateBorderFillNoDraw() { CBorderFill bfill; memset(&bfill, 0, sizeof(bfill)); //---- make a BorderFill obj with a border ---- bfill._eBgType = BT_BORDERFILL; bfill._fNoDraw = TRUE; AddItem(&bfill, NULL, L"NoDraw", GID_BORDERFILL); } //-------------------------------------------------------------------------- void CreateBorderFillSquare() { CBorderFill bfill; memset(&bfill, 0, sizeof(bfill)); //---- make a BorderFill obj with a border ---- bfill._eBgType = BT_BORDERFILL; bfill._eBorderType = BT_RECT; bfill._iBorderSize = 0; bfill._eFillType = FT_SOLID; bfill._crFill = RGB(128, 255, 255); AddItem(&bfill, NULL, L"Square", GID_BORDERFILL); } //-------------------------------------------------------------------------- void CreateBorderFillBorder() { CBorderFill bfill; memset(&bfill, 0, sizeof(bfill)); //---- make a BorderFill obj with a border ---- bfill._eBgType = BT_BORDERFILL; bfill._eBorderType = BT_RECT; bfill._crBorder = RGB(255, 128, 128); bfill._iBorderSize = 3; bfill._eFillType = FT_SOLID; bfill._crFill = RGB(128, 255, 255); AddItem(&bfill, NULL, L"Border", GID_BORDERFILL); } //-------------------------------------------------------------------------- void CreateBorderFillCircle() { CBorderFill bfill; memset(&bfill, 0, sizeof(bfill)); //---- make a BorderFill obj with a border ---- bfill._eBgType = BT_BORDERFILL; bfill._eBorderType = BT_ROUNDRECT; bfill._crBorder = RGB(255, 128, 128); bfill._iBorderSize = 3; bfill._iRoundCornerWidth = 80; bfill._iRoundCornerHeight = 80; bfill._eFillType = FT_SOLID; bfill._crFill = RGB(128, 255, 255); AddItem(&bfill, NULL, L"Circle", GID_BORDERFILL); } //-------------------------------------------------------------------------- void CreateBorderFillGradient() { CBorderFill bfill; memset(&bfill, 0, sizeof(bfill)); //---- make a BorderFill obj with a border ---- bfill._eBgType = BT_BORDERFILL; bfill._eBorderType = BT_RECT; bfill._crBorder = RGB(255, 128, 128); bfill._iBorderSize = 3; bfill._eFillType = FT_HORZGRADIENT; //---- gradients ---- bfill._iGradientPartCount = 2; bfill._crGradientColors[0] = RGB(0, 0, 0); bfill._crGradientColors[1] = RGB(255, 255, 255); bfill._iGradientRatios[0] = 0; bfill._iGradientRatios[1] = 255; AddItem(&bfill, NULL, L"Gradient", GID_BORDERFILL); } //-------------------------------------------------------------------------- void CreateBorderFillCircleGradient() { CBorderFill bfill; memset(&bfill, 0, sizeof(bfill)); //---- make a BorderFill obj with a border ---- bfill._eBgType = BT_BORDERFILL; bfill._eBorderType = BT_ROUNDRECT; bfill._crBorder = RGB(255, 128, 128); bfill._iBorderSize = 3; bfill._iRoundCornerWidth = 80; bfill._iRoundCornerHeight = 80; bfill._eFillType = FT_HORZGRADIENT; //---- gradients ---- bfill._iGradientPartCount = 2; bfill._crGradientColors[0] = RGB(0, 0, 0); bfill._crGradientColors[1] = RGB(255, 255, 255); bfill._iGradientRatios[0] = 0; bfill._iGradientRatios[1] = 255; AddItem(&bfill, NULL, L"CircleGradient", GID_BORDERFILL); } //-------------------------------------------------------------------------- void CreateImageFileBorder(SIZINGTYPE eSizeType, BOOL fSizeBorders, BOOL fForceSizeRect) { CImageFile cif; memset(&cif, 0, sizeof(cif)); cif._ImageInfo.hProcessBitmap = (HBITMAP)LoadImage(hInst, static_cast(IntToPtr(IDB_BORDERTEST)), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); //---- create a ImageFile object that sizes with STRETCH ---- cif._eBgType = BT_IMAGEFILE; if (fSizeBorders) { cif._fSourceGrow = TRUE; cif._fIntegralSizing = TRUE; } cif._fMirrorImage = TRUE; cif._iImageCount = 1; cif._eImageLayout = IL_VERTICAL; cif._ImageInfo.iSingleWidth = 18; cif._ImageInfo.iSingleHeight = 17; cif._ImageInfo.eSizingType = eSizeType; cif._ImageInfo.iMinDpi = 96; cif._szNormalSize.cx = 50; cif._szNormalSize.cy = 50; SetRect((RECT *)&cif._SizingMargins, 3, 3, 3, 3); DWORD dwOtdFlags = 0; if (fForceSizeRect) { dwOtdFlags |= OTD_FORCE_RECT_SIZING; } AddItem(&cif, NULL, L"BorderTest", GID_BORDERS, dwOtdFlags); } //-------------------------------------------------------------------------- void CreateImage(int iBgImageId, int iStateCount, SIZINGTYPE eSizeType, BOOL fSrcSizing, int iGroupId, LPCWSTR pszName, int lw, int rw, int th, int bh) { CMaxImageFile mif; memset(&mif, 0, sizeof(mif)); if (iBgImageId) { mif._ImageInfo.hProcessBitmap = (HBITMAP)LoadImage(hInst, static_cast(IntToPtr(iBgImageId)), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); } //---- create a ImageFile object ---- mif._eBgType = BT_IMAGEFILE; mif._fMirrorImage = TRUE; mif._iImageCount = iStateCount; mif._eImageLayout = IL_VERTICAL; mif._ImageInfo.eSizingType = eSizeType; mif._ImageInfo.iMinDpi = 96; mif._szNormalSize.cx = 60; mif._szNormalSize.cy = 40; mif._eGlyphType = GT_IMAGEGLYPH; //---- set Width/Height ---- BITMAP bm; GetObject(mif._ImageInfo.hProcessBitmap, sizeof bm, &bm); mif._ImageInfo.iSingleWidth = bm.bmWidth; mif._ImageInfo.iSingleHeight = bm.bmHeight/iStateCount; mif._ImageInfo.szMinSize.cx = bm.bmWidth; mif._ImageInfo.szMinSize.cy = bm.bmHeight/iStateCount; SetRect((RECT *)&mif._SizingMargins, lw, rw, th, bh); SetRect((RECT *)&mif._ContentMargins, lw, rw, th, bh); DWORD dwOtdFlags = 0; if (fSrcSizing) { dwOtdFlags |= OTD_FORCE_RECT_SIZING; } AddItem(&mif, NULL, pszName, iGroupId, dwOtdFlags); } //-------------------------------------------------------------------------- void CreateProgressTrack() { CMaxImageFile mif; memset(&mif, 0, sizeof(mif)); mif._ImageInfo.hProcessBitmap = (HBITMAP)LoadImage(hInst, static_cast(IntToPtr(IDB_PROGRESS_TRACK)), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); //---- create a ImageFile object ---- mif._eBgType = BT_IMAGEFILE; mif._fMirrorImage = TRUE; mif._iImageCount = 1; mif._eImageLayout = IL_VERTICAL; mif._ImageInfo.eSizingType = ST_TILE; mif._ImageInfo.iMinDpi = 96; mif._szNormalSize.cx = 60; mif._szNormalSize.cy = 40; //---- set Width/Height ---- BITMAP bm; GetObject(mif._ImageInfo.hProcessBitmap, sizeof bm, &bm); mif._ImageInfo.iSingleWidth = bm.bmWidth; mif._ImageInfo.iSingleHeight = bm.bmHeight/1; mif._ImageInfo.szMinSize.cx = 10; mif._ImageInfo.szMinSize.cy = 10; mif._szNormalSize.cx = 100; mif._szNormalSize.cy = 18; mif._fSourceShrink = TRUE; SetRect((RECT *)&mif._SizingMargins, 4, 4, 3, 3); SetRect((RECT *)&mif._ContentMargins, 4, 4, 3, 3); AddItem(&mif, NULL, L"Progress", GID_SRCSIZING, 0); } //-------------------------------------------------------------------------- void CreateProgressChunk() { CMaxImageFile mif; memset(&mif, 0, sizeof(mif)); //---- create a ImageFile object ---- mif._eBgType = BT_IMAGEFILE; mif._ImageInfo.hProcessBitmap = (HBITMAP)LoadImage(hInst, static_cast(IntToPtr(IDB_PROGRESS_CHUNK)), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); mif._fMirrorImage = TRUE; mif._iImageCount = 1; mif._eImageLayout = IL_VERTICAL; mif._ImageInfo.eSizingType = ST_TILE; mif._ImageInfo.iMinDpi = 96; mif._szNormalSize.cx = 60; mif._szNormalSize.cy = 40; mif._eGlyphType = GT_IMAGEGLYPH; //---- set Width/Height ---- BITMAP bm; GetObject(mif._ImageInfo.hProcessBitmap, sizeof bm, &bm); mif._ImageInfo.iSingleWidth = bm.bmWidth; mif._ImageInfo.iSingleHeight = bm.bmHeight/1; mif._ImageInfo.szMinSize.cx = 10; mif._ImageInfo.szMinSize.cy = 10; mif._szNormalSize.cx = 100; mif._szNormalSize.cy = 18; SetRect((RECT *)&mif._SizingMargins, 0, 0, 6, 5); SetRect((RECT *)&mif._ContentMargins, 0, 0, 6, 5); AddItem(&mif, NULL, L"Progress", GID_SRCSIZING, 0); } //-------------------------------------------------------------------------- void CreateRadioImage() { CMaxImageFile mif; memset(&mif, 0, sizeof(mif)); //---- create a ImageFile object ---- mif._eBgType = BT_IMAGEFILE; mif._fMirrorImage = TRUE; mif._iImageCount = 8; mif._eImageLayout = IL_VERTICAL; mif._szNormalSize.cx = 60; mif._szNormalSize.cy = 40; mif._eImageSelectType = IST_DPI; mif._iMultiImageCount = 3; mif._eTrueSizeScalingType = TSST_DPI; mif._fUniformSizing = TRUE; mif._eHAlign = HA_CENTER; mif._eVAlign = VA_CENTER; int iMinDpis[] = {96, 118, 185}; //---- process multiple images ---- for (int i=0; i < 3; i++) { DIBINFO *pdi = &mif.MultiDibs[i]; int idnum = IDB_RADIO13 + i; pdi->hProcessBitmap = (HBITMAP)LoadImage(hInst, static_cast(IntToPtr(idnum)), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); pdi->iMinDpi = iMinDpis[i]; //---- get bitmap width/height ---- BITMAP bm; GetObject(pdi->hProcessBitmap, sizeof bm, &bm); pdi->iSingleWidth = bm.bmWidth; pdi->iSingleHeight = bm.bmHeight/8; pdi->szMinSize.cx = pdi->iSingleWidth; pdi->szMinSize.cy = pdi->iSingleHeight; pdi->eSizingType = ST_TRUESIZE; pdi->crTransparent = RGB(255, 0, 255); pdi->fTransparent = TRUE; } //---- set primary image ---- mif._ImageInfo = mif.MultiDibs[0]; AddItem(&mif, NULL, L"RadioButton", GID_SRCSIZING, OTD_FORCE_RECT_SIZING); } //-------------------------------------------------------------------------- void CreateCheckImage() { CMaxImageFile mif; memset(&mif, 0, sizeof(mif)); //---- create a ImageFile object ---- mif._eBgType = BT_IMAGEFILE; mif._fMirrorImage = TRUE; mif._iImageCount = 12; mif._eImageLayout = IL_VERTICAL; mif._szNormalSize.cx = 60; mif._szNormalSize.cy = 40; mif._eImageSelectType = IST_DPI; mif._iMultiImageCount = 3; mif._eTrueSizeScalingType = TSST_DPI; mif._fUniformSizing = TRUE; mif._eHAlign = HA_CENTER; mif._eVAlign = VA_CENTER; int iMinDpis[] = {96, 118, 185}; //---- process multiple images ---- for (int i=0; i < 3; i++) { DIBINFO *pdi = &mif.MultiDibs[i]; int idnum = IDB_CHECK13 + i; pdi->hProcessBitmap = (HBITMAP)LoadImage(hInst, static_cast(IntToPtr(idnum)), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); pdi->iMinDpi = iMinDpis[i]; //---- get bitmap width/height ---- BITMAP bm; GetObject(pdi->hProcessBitmap, sizeof bm, &bm); pdi->iSingleWidth = bm.bmWidth; pdi->iSingleHeight = bm.bmHeight/12; pdi->szMinSize.cx = pdi->iSingleWidth; pdi->szMinSize.cy = pdi->iSingleHeight; pdi->eSizingType = ST_TRUESIZE; pdi->fAlphaChannel = TRUE; } //---- set primary image ---- mif._ImageInfo = mif.MultiDibs[0]; AddItem(&mif, NULL, L"CheckBox", GID_SRCSIZING, OTD_FORCE_RECT_SIZING); } //-------------------------------------------------------------------------- void CreateScrollGlyph() { CMaxImageFile mif; memset(&mif, 0, sizeof(mif)); //---- create a ImageFile object ---- mif._eBgType = BT_IMAGEFILE; mif._eGlyphType = GT_IMAGEGLYPH; mif._fMirrorImage = TRUE; mif._iImageCount = 16; mif._eImageLayout = IL_VERTICAL; mif._szNormalSize.cx = 30; mif._szNormalSize.cy = 10; mif._eImageSelectType = IST_NONE; mif._fUniformSizing = TRUE; mif._eHAlign = HA_CENTER; mif._eVAlign = VA_CENTER; SetRect((RECT *)&mif._SizingMargins, 5, 5, 5, 5); SetRect((RECT *)&mif._ContentMargins, 0, 0, 3, 3); //---- background image ---- DIBINFO *pdi = &mif._ImageInfo; pdi->hProcessBitmap = (HBITMAP)LoadImage(hInst, static_cast(IntToPtr(IDB_SCROLL_ARROWS)), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); //---- get bitmap width/height ---- BITMAP bm; GetObject(pdi->hProcessBitmap, sizeof bm, &bm); pdi->iSingleWidth = bm.bmWidth; pdi->iSingleHeight = bm.bmHeight/16; pdi->szMinSize.cx = pdi->iSingleWidth; pdi->szMinSize.cy = pdi->iSingleHeight; pdi->iMinDpi = 96; pdi->eSizingType = ST_STRETCH; //---- glyph image ---- pdi = &mif._GlyphInfo; mif._GlyphInfo.hProcessBitmap = (HBITMAP)LoadImage(hInst, static_cast(IntToPtr(IDB_SCROLL_GLPYHS)), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); pdi->fTransparent = TRUE; pdi->crTransparent = RGB(255, 0, 255); GetObject(pdi->hProcessBitmap, sizeof bm, &bm); pdi->iSingleWidth = bm.bmWidth; pdi->iSingleHeight = bm.bmHeight/16; pdi->szMinSize.cx = pdi->iSingleWidth; pdi->szMinSize.cy = pdi->iSingleHeight; pdi->iMinDpi = 96; pdi->eSizingType = ST_TRUESIZE; mif._fSourceShrink = TRUE; mif._fSourceGrow = TRUE; mif._eTrueSizeScalingType = TSST_SIZE; mif._iTrueSizeStretchMark = 100; //---- add it (without OTD_FORCE_RECT_SIZING) ---- AddItem(&mif, NULL, L"ScrollBox", GID_SRCSIZING, 0); } //-------------------------------------------------------------------------- void CreateImageFileStretch(IMAGEFILEDRAW eDraw, int iGroupId) { CImageFile cif; memset(&cif, 0, sizeof(cif)); int idnum = IDB_STRETCH; if (eDraw == IF_TRANS) idnum = IDB_STRETCH_TRANS; cif._ImageInfo.hProcessBitmap = (HBITMAP)LoadImage(hInst, static_cast(IntToPtr(idnum)), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); //---- create a ImageFile object that sizes with STRETCH ---- cif._eBgType = BT_IMAGEFILE; cif._fMirrorImage = TRUE; cif._iImageCount = 5; cif._eImageLayout = IL_VERTICAL; cif._ImageInfo.iSingleWidth = 20; cif._ImageInfo.iSingleHeight = 19; cif._ImageInfo.eSizingType = ST_STRETCH; if (eDraw == IF_TRANS) { cif._ImageInfo.fTransparent = TRUE; cif._ImageInfo.crTransparent = RGB(255, 0, 255); } SetRect((RECT *)&cif._SizingMargins, 4, 4, 4, 4); LPCWSTR p = L"Stretch"; if (eDraw == IF_TRANS) p = L"Stretch+Trans"; AddItem(&cif, NULL, p, iGroupId); } //-------------------------------------------------------------------------- void CreateImageFileTile(IMAGEFILEDRAW eDraw, int iGroupId) { CImageFile cif; memset(&cif, 0, sizeof(cif)); int idnum = IDB_TILE; if (eDraw == IF_TRANS) idnum = IDB_TILE_TRANS; DIBINFO *pdi = &cif._ImageInfo; pdi->hProcessBitmap = (HBITMAP)LoadImage(hInst, static_cast(IntToPtr(idnum)), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); //---- create a ImageFile object that sizes with TILE ---- pdi->eSizingType = ST_TILE; cif._eBgType = BT_IMAGEFILE; cif._fMirrorImage = TRUE; cif._iImageCount = 5; cif._eImageLayout = IL_VERTICAL; cif._ImageInfo.iSingleWidth = 20; cif._ImageInfo.iSingleHeight = 19; if (eDraw == IF_TRANS) { cif._ImageInfo.fTransparent = TRUE; cif._ImageInfo.crTransparent = RGB(255, 0, 255); } SetRect((RECT *)&cif._SizingMargins, 4, 4, 9, 9); LPCWSTR p = L"Tile"; if (eDraw == IF_TRANS) p = L"Tile+Trans"; AddItem(&cif, NULL, p, iGroupId); } //-------------------------------------------------------------------------- void CreateImageFileTrueSize(IMAGEFILEDRAW eDraw, int iGroupId) { CImageFile cif; memset(&cif, 0, sizeof(cif)); int idnum = IDB_TRUE; if (eDraw == IF_TRANS) idnum = IDB_TRUE_TRANS; else if (eDraw == IF_ALPHA) idnum = IDB_TRUE_ALPHA; cif._ImageInfo.hProcessBitmap = (HBITMAP)LoadImage(hInst, static_cast(IntToPtr(idnum)), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); //---- create a ImageFile object that sizes with STRETCH ---- cif._eBgType = BT_IMAGEFILE; cif._iImageCount = 8; cif._fMirrorImage = TRUE; cif._eImageLayout = IL_HORIZONTAL; cif._ImageInfo.iSingleWidth = 16; cif._ImageInfo.iSingleHeight = 16; cif._ImageInfo.eSizingType = ST_TRUESIZE; if (eDraw == IF_TRANS) { cif._ImageInfo.fTransparent = TRUE; cif._ImageInfo.crTransparent = RGB(255, 0, 255); } else if (eDraw == IF_ALPHA) { cif._ImageInfo.fAlphaChannel = TRUE; } LPCWSTR p = L"TrueSize"; if (eDraw == IF_TRANS) p = L"True+Trans"; else if (eDraw == IF_ALPHA) p = L"True+Alpha"; AddItem(&cif, NULL, p, iGroupId); } //-------------------------------------------------------------------------- void CreateImageFileCharGlyph() { CImageFile cif; memset(&cif, 0, sizeof(cif)); int idnum = IDB_GLYPHBG; cif._ImageInfo.hProcessBitmap = (HBITMAP)LoadImage(hInst, static_cast(IntToPtr(idnum)), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); //---- specify bg info ---- cif._eBgType = BT_IMAGEFILE; cif._fMirrorImage = TRUE; cif._iImageCount = 3; cif._eImageLayout = IL_HORIZONTAL; cif._ImageInfo.iSingleWidth = 16; cif._ImageInfo.iSingleHeight = 22; cif._ImageInfo.eSizingType = ST_STRETCH; SetRect((RECT *)&cif._SizingMargins, 1, 1, 1, 1); //---- specify the char/font info ---- cif._eGlyphType = GT_FONTGLYPH; cif._crGlyphTextColor = RGB(0, 0, 255); cif._iGlyphIndex = 62; cif._lfGlyphFont.lfWeight = FW_NORMAL; cif._lfGlyphFont.lfHeight = CLIPPER_FONTHEIGHT; lstrcpy(cif._lfGlyphFont.lfFaceName, L"marlett"); //---- specify alignment ---- cif._eHAlign = HA_CENTER; cif._eVAlign = VA_CENTER; LPCWSTR p = L"FontGlyph"; AddItem(&cif, NULL, p, GID_GLYPH); } //-------------------------------------------------------------------------- void CreateImageFileImageGlyph(IMAGEFILEDRAW eDraw, BOOL fForceMirror) { CImageFile cif; memset(&cif, 0, sizeof(cif)); int idnum = IDB_GLYPHBG; cif._ImageInfo.hProcessBitmap = (HBITMAP)LoadImage(hInst, static_cast(IntToPtr(idnum)), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); //---- specify bg info ---- cif._eBgType = BT_IMAGEFILE; cif._fMirrorImage = TRUE; cif._eGlyphType = GT_IMAGEGLYPH; cif._iImageCount = 3; cif._eImageLayout = IL_HORIZONTAL; cif._ImageInfo.iSingleWidth = 16; cif._ImageInfo.iSingleHeight = 22; cif._ImageInfo.eSizingType = ST_STRETCH; SetRect((RECT *)&cif._SizingMargins, 1, 1, 1, 1); //---- specify glyph info ---- WCHAR szName[MAX_PATH]; if (eDraw == IF_REG) { idnum = IDB_GLYPH; lstrcpy(szName, L"ImageGlyph"); cif._GlyphInfo.iSingleWidth = 10; cif._GlyphInfo.iSingleHeight = 7; } else if (eDraw == IF_TRANS) { idnum = IDB_GLYPH_TRANS; lstrcpy(szName, L"ImageTrans"); cif._GlyphInfo.fTransparent = TRUE; cif._GlyphInfo.crTransparent = RGB(255, 0, 255); cif._GlyphInfo.iSingleWidth = 10; cif._GlyphInfo.iSingleHeight = 7; } else { idnum = IDB_GLYPH_ALPHA; lstrcpy(szName, L"ImageAlpha"); cif._GlyphInfo.fAlphaChannel = TRUE; cif._GlyphInfo.iSingleWidth = 16; cif._GlyphInfo.iSingleHeight = 16; } cif._GlyphInfo.hProcessBitmap = (HBITMAP)LoadImage(hInst, static_cast(IntToPtr(idnum)), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); //---- specify alignment ---- cif._eHAlign = HA_CENTER; cif._eVAlign = VA_CENTER; DWORD dwDtbFlags = 0; if (fForceMirror) { dwDtbFlags |= DTBG_MIRRORDC; lstrcat(szName, L"+M"); } AddItem(&cif, NULL, szName, GID_GLYPH, 0, dwDtbFlags); } //-------------------------------------------------------------------------- void CreateMultiImage() { CMaxImageFile MaxIf; memset(&MaxIf, 0, sizeof(MaxIf)); //---- specify general info ---- MaxIf._eBgType = BT_IMAGEFILE; MaxIf._fMirrorImage = TRUE; MaxIf._iImageCount = 8; MaxIf._eImageLayout = IL_VERTICAL; MaxIf._eImageSelectType = IST_SIZE; MaxIf._iMultiImageCount = 3; MaxIf._iTrueSizeStretchMark = 50; MaxIf._eTrueSizeScalingType = TSST_SIZE; MaxIf._fUniformSizing = TRUE; MaxIf._eHAlign = HA_CENTER; MaxIf._eVAlign = VA_CENTER; int iUsageSizes[] = {20, 24, 32}; //---- specify alignment ---- MaxIf._eHAlign = HA_CENTER; MaxIf._eVAlign = VA_CENTER; for (int i=0; i < MaxIf._iMultiImageCount; i++) { int idnum = IDB_MULTI1 + i; DIBINFO *pdi = &MaxIf.MultiDibs[i]; pdi->hProcessBitmap = (HBITMAP)LoadImage(hInst, static_cast(IntToPtr(idnum)), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); pdi->szMinSize.cx = iUsageSizes[i]; pdi->szMinSize.cy = iUsageSizes[i]; //---- get bitmap width/height ---- BITMAP bm; GetObject(pdi->hProcessBitmap, sizeof bm, &bm); pdi->iSingleWidth = bm.bmWidth; pdi->iSingleHeight = bm.bmHeight/8; pdi->eSizingType = ST_TRUESIZE; pdi->fAlphaChannel = TRUE; } //---- set primary image ---- MaxIf._ImageInfo = MaxIf.MultiDibs[0]; AddItem(&MaxIf, NULL, L"MultiImage", GID_MULTIIMAGE); } //-------------------------------------------------------------------------- void CreateTextObj() { CTextDraw td; memset(&td, 0, sizeof(td)); //---- text ---- td._crText = RGB(255, 128, 128); // red //---- font ---- td._fHaveFont = TRUE; td._lfFont.lfWeight = FW_NORMAL; td._lfFont.lfHeight = CLIPPER_FONTHEIGHT; td._lfFont.lfQuality = ANTIALIASED_QUALITY; lstrcpy(td._lfFont.lfFaceName, L"arial"); AddItem(NULL, &td, L"TextObj", GID_TEXT); } //-------------------------------------------------------------------------- void CreateShadowTextObj() { CTextDraw td; memset(&td, 0, sizeof(td)); //---- text ---- td._crText = RGB(255, 139, 139); // light red //---- font ---- td._fHaveFont = TRUE; td._lfFont.lfWeight = FW_NORMAL; td._lfFont.lfHeight = CLIPPER_FONTHEIGHT; td._lfFont.lfQuality = ANTIALIASED_QUALITY; lstrcpy(td._lfFont.lfFaceName, L"arial"); //---- shadow ---- td._ptShadowOffset.x = 2; td._ptShadowOffset.y = 2; td._crShadow = RGB(149, 0, 0); // dark red td._eShadowType = TST_SINGLE; AddItem(NULL, &td, L"ShadowText", GID_TEXT); } //-------------------------------------------------------------------------- void CreateBorderTextObj() { CTextDraw td; memset(&td, 0, sizeof(td)); //---- text ---- td._crText = RGB(255, 139, 139); // light red //---- font ---- td._fHaveFont = TRUE; td._lfFont.lfWeight = FW_NORMAL; td._lfFont.lfHeight = CLIPPER_FONTHEIGHT; td._lfFont.lfQuality = ANTIALIASED_QUALITY; lstrcpy(td._lfFont.lfFaceName, L"arial"); //---- border ---- td._iBorderSize = 1; td._crBorder = RGB(128, 128, 255); // light blue AddItem(NULL, &td, L"BorderText", GID_TEXT); } //-------------------------------------------------------------------------- void CreateBorderShadowTextObj() { CTextDraw td; memset(&td, 0, sizeof(td)); //---- text ---- td._crText = RGB(255, 139, 139); // light red //---- font ---- td._fHaveFont = TRUE; td._lfFont.lfWeight = FW_NORMAL; td._lfFont.lfHeight = CLIPPER_FONTHEIGHT; td._lfFont.lfQuality = ANTIALIASED_QUALITY; lstrcpy(td._lfFont.lfFaceName, L"arial"); //---- shadow ---- td._ptShadowOffset.x = 2; td._ptShadowOffset.y = 2; td._crShadow = RGB(149, 0, 0); // dark red td._eShadowType = TST_SINGLE; //---- border ---- td._iBorderSize = 1; td._crBorder = RGB(0, 0, 0); // black AddItem(NULL, &td, L"BorderShadow", GID_TEXT); } //-------------------------------------------------------------------------- void CreateBlurShadowTextObj() { CTextDraw td; memset(&td, 0, sizeof(td)); //---- text ---- td._crText = RGB(255, 139, 139); // light red //---- font ---- td._fHaveFont = TRUE; td._lfFont.lfWeight = FW_NORMAL; td._lfFont.lfHeight = CLIPPER_FONTHEIGHT; td._lfFont.lfQuality = ANTIALIASED_QUALITY; lstrcpy(td._lfFont.lfFaceName, L"arial"); //---- shadow ---- td._ptShadowOffset.x = 2; td._ptShadowOffset.y = 2; td._crShadow = RGB(149, 0, 0); // dark red td._eShadowType = TST_CONTINUOUS; AddItem(NULL, &td, L"BlurShadow", GID_TEXT); } //-------------------------------------------------------------------------- void LabelClip(HDC hdc, RECT *prc, int iColIndex, LPCWSTR pszName) { int left = prc->left + (iColIndex+1)*szCell.cx; int top = prc->top + 6; // some padding from very top of window //---- manual page clipping ---- if ((top + szCell.cy) < 0) return; if (top > iVertPageSize) return; TextOut(hdc, left, top, pszName, wcslen(pszName)); } //-------------------------------------------------------------------------- void CreateDrawObjects() { //---- borderfill group ---- CreateBorderFillNoDraw(); CreateBorderFillSquare(); CreateBorderFillBorder(); CreateBorderFillCircle(); CreateBorderFillGradient(); CreateBorderFillCircleGradient(); //---- imagefile group ---- CreateImageFileStretch(IF_REG, GID_IMAGEFILE); CreateImageFileStretch(IF_TRANS, GID_IMAGEFILE); CreateImageFileTile(IF_REG, GID_IMAGEFILE); CreateImageFileTile(IF_TRANS, GID_IMAGEFILE); CreateImageFileTrueSize(IF_REG, GID_IMAGEFILE); CreateImageFileTrueSize(IF_TRANS, GID_IMAGEFILE); CreateImageFileTrueSize(IF_ALPHA, GID_IMAGEFILE); //---- glyph group ---- //CreateImageFileCharGlyph(); CreateImageFileImageGlyph(IF_REG, FALSE); CreateImageFileImageGlyph(IF_TRANS, FALSE); CreateImageFileImageGlyph(IF_TRANS, TRUE); CreateImageFileImageGlyph(IF_ALPHA, FALSE); //---- MultiImage group ---- CreateMultiImage(); //---- text group ---- CreateTextObj(); CreateShadowTextObj(); CreateBorderTextObj(); CreateBorderShadowTextObj(); CreateBlurShadowTextObj(); //---- borders group ---- CreateImageFileBorder(ST_TRUESIZE, FALSE, FALSE); CreateImageFileBorder(ST_STRETCH, FALSE, FALSE); CreateImageFileBorder(ST_STRETCH, TRUE, TRUE); CreateImageFileBorder(ST_TILE, TRUE, TRUE); //---- SrcSizing group ---- CreateImage(IDB_PUSHBUTTON, 5, ST_STRETCH, TRUE, GID_SRCSIZING, L"PushButton", 8, 8, 9, 9); CreateRadioImage(); CreateCheckImage(); CreateScrollGlyph(); CreateProgressTrack(); CreateProgressChunk(); } //-------------------------------------------------------------------------- void CenterRect(POINT &ptCenter, int iSize, RECT *prc) { int iSizeA = iSize/2; int iSizeB = iSize - iSizeA; prc->left = ptCenter.x - iSizeA; prc->right = ptCenter.x + iSizeB; prc->top = ptCenter.y - iSizeA; prc->bottom = ptCenter.y + iSizeB; } //-------------------------------------------------------------------------- void DrawMultiImages(HDC hdc, RECT *prc, HTHEME hTheme) { SIZE szMyCell = {80, 80}; int iRowIndex = 0; int iSizes[] = {12, 16, 20, 24, 32, 48, 64}; //---- draw various sizes of image ---- for (int iIndex=0; iIndex < ARRAYSIZE(iSizes); iIndex++) { int iSize = iSizes[iIndex]; //---- label object on left ---- int left = prc->left + 4; // some padding away from edge int top = prc->top + (iRowIndex)*szMyCell.cy + 18; // try to center //---- manual page clipping ---- if ((top + szMyCell.cy) < 0) return; if (top > iVertPageSize) return; WCHAR szName[MAX_PATH]; wsprintf(szName, L"Size: %d", iSize); TextOut(hdc, left, top+15, szName, wcslen(szName)); //---- draw image in all of its states ---- int iPartId = BP_RADIOBUTTON; for (int iStateId=RBS_UNCHECKEDNORMAL; iStateId <= RBS_CHECKEDDISABLED; iStateId++) { left += szMyCell.cx; RECT rc = {left, top, left+szMyCell.cx, top+szMyCell.cy}; //---- draw purple target dashed rect ---- DrawTargetRect(hdc, &rc, RGB(128, 128, 255)); //---- calc center pt ---- POINT ptCenter = {left + szMyCell.cx/2, top + szMyCell.cy/2}; //---- rect to draw into ---- CenterRect(ptCenter, iSize, &rc); //---- draw red rect for "draw into" rect ---- DrawTargetRect(hdc, &rc, RGB(255, 0, 0)); HRESULT hr = DrawThemeBackground(hTheme, hdc, iPartId, iStateId, &rc, NULL); if (FAILED(hr)) { WCHAR buff[100]; wsprintf(buff, L"DrawThemeBackground err: hr=0x%x, irow=%d, iPartId=%d", hr, iRowIndex, iPartId); //MessageBox(NULL, buff, L"Error", MB_OK); } } iRowIndex++; } } //-------------------------------------------------------------------------- void DrawBorders(HDC hdc, RECT *prc, TESTITEM *pTestItem) { int top = prc->top + 4; int left = prc->left + 6; //---- message on top line ---- WCHAR szBuff[100]; lstrcpy(szBuff, L"Image: BorderTest.bmp, 18x17, 24 bit, Sizing Margins: 3, 3, 3, 3"); TextOut(hdc, left, top+15, szBuff, wcslen(szBuff)); top += 44; //---- FIRST row: draw border test obj in 6 different sizes ---- SIZE szMyCell = {120, 120}; //---- manual page clipping ---- if (((top + szMyCell.cy) >= 0) && (top <= iVertPageSize)) { LPCWSTR pszLabels [] = { L"TrueSize", L"Stretch", L"Stretch", L"Stretch", L"Stretch", L"Stretch", L"Stretch"}; SIZE szSizes[] = { {60, 40}, {60, 40}, {6, 40}, {3, 40}, {60, 6}, {60, 2}, {2, 3} }; //---- draw various sizes of image ---- for (int iIndex=0; iIndex < ARRAYSIZE(szSizes); iIndex++) { SIZE sz = szSizes[iIndex]; //---- label object on top ---- left = prc->left + iIndex*szMyCell.cx + 6; // some padding away from edge wsprintf(szBuff, L"%s (%dx%d)", pszLabels[iIndex], sz.cx, sz.cy); TextOut(hdc, left, top+15, szBuff, wcslen(szBuff)); //---- draw image ---- RECT rc = {left, top+50, left+sz.cx, top+50+sz.cy}; int i = (iIndex==0) ? 0 : 1; HRESULT hr = DrawThemeBackground(pTestItem[i].hTheme, hdc, 0, 0, &rc, NULL); if (FAILED(hr)) { WCHAR buff[100]; wsprintf(buff, L"DrawThemeBackground err in DrawBorders: hr=0x%x, iIndex=%d", hr, iIndex); //MessageBox(NULL, buff, L"Error", MB_OK); } } } //---- SECOND row: draw 2 other border objects real big (test border scaling) ---- top += szMyCell.cy; szMyCell.cx = 380; szMyCell.cy = 300; SIZE sz = {szMyCell.cx - 30, szMyCell.cy - (50 + 10)}; //---- manual page clipping: first row ---- if (((top + szMyCell.cy) >= 0) && (top <= iVertPageSize)) { LPCWSTR pszLabels [] = { L"Border Scaling (stretch)", L"Border Scaling (tile)"}; //---- draw various sizes of image ---- for (int iIndex=0; iIndex < ARRAYSIZE(pszLabels); iIndex++) { //---- label object on top ---- int left = prc->left + iIndex*szMyCell.cx + 6; // some padding away from edge TextOut(hdc, left, top+15, pszLabels[iIndex], wcslen(pszLabels[iIndex])); //---- draw image ---- RECT rc = {left, top+50, left+sz.cx, top+50+sz.cy}; HRESULT hr = DrawThemeBackground(pTestItem[2+iIndex].hTheme, hdc, 0, 0, &rc, NULL); if (FAILED(hr)) { WCHAR buff[100]; wsprintf(buff, L"DrawThemeBackground err in DrawBorders: hr=0x%x, iIndex=%d", hr, iIndex); //MessageBox(NULL, buff, L"Error", MB_OK); } } } } //-------------------------------------------------------------------------- void DrawSrcSizing(HDC hdc, RECT *prc, TESTITEM *pTestItem) { SIZE szMyCell = {120, 110}; int top = prc->top + 4; int left = prc->left + szMyCell.cx + 6; //---- labels on top line ---- LPCWSTR TopLabels[] = {L"Small", L"Regular", L"Large", L"High DPI"}; SIZE szStretchSizes[] = { {50, 6}, {75, 23}, {90, 65}, {340, 100} }; SIZE szTrueSizes[] = { {10, 6}, {13, 13}, {30, 30}, {340, 100} }; int iStates[] = {5, 6, 6, 0, 0}; for (int i=0; i < ARRAYSIZE(TopLabels); i++) { TextOut(hdc, left, top, TopLabels[i], wcslen(TopLabels[i])); left += szMyCell.cx; } top += 30; //---- draw rows ---- for (int iRow=0; iRow < 5; iRow++) { //---- draw name on left ---- left = prc->left + 6; WCHAR *pszName = pTestItem[iRow].szName; TextOut(hdc, left, top-5, pszName, wcslen(pszName)); for (int iSize=0; iSize < ARRAYSIZE(szStretchSizes); iSize++) { left += szMyCell.cx; SIZE *psz; if ((iRow > 0) && (iRow < 4)) { psz = &szTrueSizes[iSize]; } else { psz = &szStretchSizes[iSize]; } RECT rc = {left, top, left + psz->cx, top + psz->cy}; HTHEME hTheme = pTestItem[iRow].hTheme; if (hTheme) { DrawThemeBackground(hTheme, hdc, 0, iStates[iRow], &rc, NULL); if (iRow == 4) // progress control { RECT rcContent; GetThemeBackgroundContentRect(hTheme, hdc, 0, 0, &rc, &rcContent); DrawThemeBackground(pTestItem[5].hTheme, hdc, 0, iStates[iRow], &rcContent, NULL); } } } top += szMyCell.cy; } } //-------------------------------------------------------------------------- void PaintObjects(HDC hdc, RECT *prc, int iGroupId) { //---- select in a fixed size font for resolution-independent bits ---- HFONT hfFixedSize = CreateFont(18, 6, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, L"MS Sans Serif"); HFONT hOldFont = (HFONT)SelectObject(hdc, hfFixedSize); RECT rc = *prc; rc.top -= iVertOffset; rc.bottom -= iVertOffset; if (iGroupId == GID_TEXT) // text object { for (int i=0; i < iItemCount[iGroupId]; i++) { DrawTextObjects(TestItems[iGroupId][i].hTheme, hdc, &rc, i, TestItems[iGroupId][i].szName); } } else if (iGroupId == GID_MULTIIMAGE) { DrawMultiImages(hdc, prc, TestItems[iGroupId][0].hTheme); } else if (iGroupId == GID_BORDERS) { DrawBorders(hdc, prc, TestItems[iGroupId]); } else if (iGroupId == GID_SRCSIZING) { DrawSrcSizing(hdc, prc, TestItems[iGroupId]); } else { LabelClip(hdc, &rc, 0, L"NoClip"); LabelClip(hdc, &rc, 1, L"OverClip"); LabelClip(hdc, &rc, 2, L"ExactClip"); LabelClip(hdc, &rc, 3, L"PartialClip"); LabelClip(hdc, &rc, 4, L"InOut1"); LabelClip(hdc, &rc, 5, L"InOut2"); LabelClip(hdc, &rc, 6, L"OutClip"); for (int i=0; i < iItemCount[iGroupId]; i++) { DrawClips(TestItems[iGroupId][i].hTheme, hdc, &rc, i, TestItems[iGroupId][i].szName, TestItems[iGroupId][i].dwDtbFlags); } } //---- restore the font ---- SelectObject(hdc, hOldFont); DeleteObject(hfFixedSize); } //-------------------------------------------------------------------------- void RegisterWindowClasses() { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); //---- register MAIN window class ---- wcex.style = 0; wcex.lpfnWndProc = (WNDPROC)MainWndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInst; wcex.hIcon = LoadIcon(hInst, (LPCTSTR)IDI_CLIPPER); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = (LPCWSTR)IDC_CLIPPER; wcex.lpszClassName = pszMainWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); RegisterClassEx(&wcex); //---- register DISPLAY window class ---- wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)DisplayWndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInst; wcex.hIcon = LoadIcon(hInst, (LPCTSTR)IDI_CLIPPER); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = (LPCWSTR)IDC_CLIPPER; wcex.lpszClassName = pszDisplayWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); RegisterClassEx(&wcex); } //-------------------------------------------------------------------------- BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // Store instance handle in our global variable CreateDrawObjects(); if (! CreateAllWindows()) return FALSE; ShowWindow(hwndMain, nCmdShow); UpdateWindow(hwndMain); return TRUE; } //-------------------------------------------------------------------------- void HandleVScroll(int message, WPARAM wParam, LPARAM lParam) { int iOldVertOffset = iVertOffset; if (message == WM_VSCROLL) { switch (LOWORD(wParam)) { case SB_LINEUP: iVertOffset -= iVertLineSize; break; case SB_LINEDOWN: iVertOffset += iVertLineSize; break; case SB_PAGEUP: iVertOffset -= iVertPageSize; break; case SB_PAGEDOWN: iVertOffset += iVertPageSize; break; case SB_THUMBPOSITION: iVertOffset = HIWORD(wParam); break; } } else // mouse wheel { iVertOffset -= (GET_WHEEL_DELTA_WPARAM(wParam)/10); } //---- keep in valid range ---- if (iVertOffset < 0) { iVertOffset = 0; } else if (iVertOffset > iMaxVertOffset) { iVertOffset = iMaxVertOffset; } //---- scroll or repaint, as needed ---- if (iVertOffset != iOldVertOffset) { SetScrollPos(hwndDisplay, SB_VERT, iVertOffset, TRUE); int iDiff = (iVertOffset - iOldVertOffset); if (abs(iDiff) >= iVertPageSize) { InvalidateRect(hwndDisplay, NULL, TRUE); } else { ScrollWindowEx(hwndDisplay, 0, -iDiff, NULL, NULL, NULL, NULL, SW_INVALIDATE | SW_ERASE); } } } //-------------------------------------------------------------------------- void OnDisplayResize() { int iTabNum = TabCtrl_GetCurSel(hwndTab); if (iTabNum < 0) iTabNum = 0; int iGroupId = iTabNum/2; RECT rc; GetClientRect(hwndDisplay, &rc); iVertPageSize = RECTHEIGHT(rc); iMaxVertOffset = ((iItemCount[iGroupId]+1)*szCell.cy) - iVertPageSize; if (iMaxVertOffset < 0) iMaxVertOffset = 0; if (iVertOffset > iMaxVertOffset) iVertOffset = iMaxVertOffset; //---- set scrolling info ---- SetScrollRange(hwndDisplay, SB_VERT, 0, iMaxVertOffset, FALSE); SetScrollPos(hwndDisplay, SB_VERT, iVertOffset, TRUE); } //-------------------------------------------------------------------------- LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; int iWidth, iHeight; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_NOTIFY: NMHDR *phdr; phdr = (NMHDR *)lParam; if (phdr->code == TCN_SELCHANGE) // tab selection { iVertOffset = 0; OnDisplayResize(); InvalidateRect(hwndDisplay, NULL, TRUE); } break; case WM_SIZE: iWidth = LOWORD(lParam); iHeight = HIWORD(lParam); MoveWindow(hwndTab, 0, 0, iWidth, iHeight, TRUE); RECT rc; SetRect(&rc, 0, 0, iWidth, iHeight); TabCtrl_AdjustRect(hwndTab, FALSE, &rc); MoveWindow(hwndDisplay, rc.left, rc.top, RECTWIDTH(rc), RECTHEIGHT(rc), TRUE); break; case WM_MOUSEWHEEL: HandleVScroll(message, wParam, lParam); return 0; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } //-------------------------------------------------------------------------- LRESULT CALLBACK DisplayWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; int iTabNum = TabCtrl_GetCurSel(hwndTab); if (iTabNum < 0) iTabNum = 0; int iGroupId = iTabNum/2; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: RECT rt; hdc = BeginPaint(hWnd, &ps); if (iTabNum % 2) // if its a mirrored page SetLayout(hdc, LAYOUT_RTL); else SetLayout(hdc, 0); GetClientRect(hWnd, &rt); PaintObjects(hdc, &rt, iGroupId); EndPaint(hWnd, &ps); break; case WM_VSCROLL: HandleVScroll(message, wParam, lParam); return 0; case WM_SIZE: OnDisplayResize(); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } //-------------------------------------------------------------------------- BOOL CreateAllWindows() { TCITEM tci = {0}; BOOL fOk = FALSE; int i; //---- create main window ---- hwndMain = CreateWindow(pszMainWindowClass, L"Clipper", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInst, NULL); if (! hwndMain) goto exit; //---- create tab control covering main client area ---- RECT rc; GetClientRect(hwndMain, &rc); hwndTab = CreateWindowEx(0, WC_TABCONTROL, L"", WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|TCS_MULTILINE|TCS_HOTTRACK|WS_VISIBLE, rc.left, rc.top, (int)RECTWIDTH(&rc), (int)RECTHEIGHT(&rc), hwndMain, NULL, hInst, NULL); if (! hwndTab) goto exit; //---- create the display window in the tab control "display area" ---- hwndDisplay = CreateWindow(pszDisplayWindowClass, L"", WS_CHILD|WS_VSCROLL|WS_VISIBLE, rc.left, rc.top, (int)RECTWIDTH(&rc), (int)RECTHEIGHT(&rc), hwndTab, NULL, hInst, NULL); if (! hwndDisplay) goto exit; //---- add tab pages ---- tci.mask = TCIF_TEXT; TabCtrl_SetPadding(hwndTab, 7, 3); for (i=0; i < ARRAYSIZE(szPageNames); i++) { tci.pszText = (LPWSTR)szPageNames[i]; SendMessage(hwndTab, TCM_INSERTITEM, i, (LPARAM)&tci); } fOk = TRUE; exit: return fOk; } //-------------------------------------------------------------------------- LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return TRUE; } break; } return FALSE; } //--------------------------------------------------------------------------