void cImage::DrawAlpha( HDC hdc, int x, int y, RECT& rcSour, BYTE alpha) { DWORD sourW = rcSour.right - rcSour.left; DWORD sourH = rcSour.bottom - rcSour.top; DWORD sourX = rcSour.left; DWORD sourY = rcSour.top; m_BlendFunc.SourceConstantAlpha = alpha; //컬러키값이 있을때.... if( m_TransColorKey != -1 ){ //1. hdc TargetDC 내용을 BlendDC 에 그린다. BitBlt( m_BlendDC, 0, 0, sourW, sourH, hdc, x, y, SRCCOPY ); //2. Sour의 내용을 BlendDC 에 그린다. GdiTransparentBlt( m_BlendDC, //Target DC 0, 0, //Target DC 위치 sourW, sourH, //크리기 가로세로 량 m_BitDC, //Source DC sourX, sourY, //Source 시작 sourW, sourH, m_TransColorKey ); //3. BlendDC 의 내용을 hdc 에 Alpha 블렌드로 그린다. GdiAlphaBlend( hdc, x, y, sourW, sourH, m_BlendDC, 0, 0, sourW, sourH, m_BlendFunc ); } //컬러 키 값이 없을때.. else{ GdiAlphaBlend( hdc, x, y, sourW, sourH, m_BitDC, sourX, sourY, sourW, sourH, m_BlendFunc ); } }
void cImage::DrawAlpha( HDC hdc, int x, int y, BYTE alpha ) { m_BlendFunc.SourceConstantAlpha = alpha; //컬러키값이 있을때.... if( m_TransColorKey != -1 ){ //1. hdc TargetDC 내용을 BlendDC 에 그린다. BitBlt( m_BlendDC, 0, 0, m_dwWidth, m_dwHeight, hdc, x, y, SRCCOPY ); //2. Sour의 내용을 BlendDC 에 그린다. GdiTransparentBlt( m_BlendDC, //Target DC 0, 0, //Target DC 위치 m_dwWidth, m_dwHeight, //크리기 가로세로 량 m_BitDC, //Source DC 0, 0, //Source 시작 m_dwWidth, m_dwHeight, m_TransColorKey ); //3. BlendDC 의 내용을 hdc 에 Alpha 블렌드로 그린다. GdiAlphaBlend( hdc, x, y, m_dwWidth, m_dwHeight, m_BlendDC, 0, 0, m_dwWidth, m_dwHeight, m_BlendFunc ); } //컬러 키 값이 없을때.. else{ GdiAlphaBlend( hdc, x, y, m_dwWidth, m_dwHeight, m_BitDC, 0, 0, m_dwWidth, m_dwHeight, m_BlendFunc ); } }
/** * render basic button content like nickname and icon. Used for the basic layouts * only. Pretty much the same code as used for the tabs. * * @param hdc : target device context * @param rcItem : rectangle to render into */ void CSideBarButton::renderIconAndNick(const HDC hdc, const RECT *rcItem) const { HICON hIcon; RECT rc = *rcItem; DWORD dwTextFlags = DT_SINGLELINE | DT_VCENTER; int stateId = m_buttonControl->stateId; int iSize = 16; const TContainerData *pContainer = m_sideBar->getContainer(); if (m_dat && pContainer) { hIcon = m_dat->cache->getIcon(iSize); if (m_dat->mayFlashTab == FALSE || (m_dat->mayFlashTab == TRUE && m_dat->bTabFlash != 0) || !(pContainer->dwFlagsEx & TCF_FLASHICON)) { DWORD ix = rc.left + 4; DWORD iy = (rc.bottom + rc.top - iSize) / 2; if (m_dat->dwFlagsEx & MWF_SHOW_ISIDLE && PluginConfig.m_bIdleDetect) CSkin::DrawDimmedIcon(hdc, ix, iy, iSize, iSize, hIcon, 180); else ::DrawIconEx(hdc, ix, iy, hIcon, iSize, iSize, 0, NULL, DI_NORMAL | DI_COMPAT); } rc.left += (iSize + 7); /* * draw the close button if enabled */ if (m_sideBar->getContainer()->dwFlagsEx & TCF_CLOSEBUTTON) { if (m_sideBar->getHoveredClose() != this) CSkin::m_default_bf.SourceConstantAlpha = 150; GdiAlphaBlend(hdc, rc.right - 20, (rc.bottom + rc.top - 16) / 2, 16, 16, CSkin::m_tabCloseHDC, 0, 0, 16, 16, CSkin::m_default_bf); rc.right -= 19; CSkin::m_default_bf.SourceConstantAlpha = 255; } ::SetBkMode(hdc, TRANSPARENT); if (m_dat->mayFlashTab == FALSE || (m_dat->mayFlashTab == TRUE && m_dat->bTabFlash != 0) || !(pContainer->dwFlagsEx & TCF_FLASHLABEL)) { bool fIsActive = (m_sideBar->getActiveItem() == this ? true : false); COLORREF clr = 0; dwTextFlags |= DT_WORD_ELLIPSIS; if (fIsActive || stateId == PBS_PRESSED) clr = PluginConfig.tabConfig.colors[1]; else if (stateId == PBS_HOT) clr = PluginConfig.tabConfig.colors[3]; else clr = PluginConfig.tabConfig.colors[0]; CSkin::RenderText(hdc, m_buttonControl->hThemeButton, m_dat->newtitle, &rc, dwTextFlags, CSkin::m_glowSize, clr); } } }
void ImageFType::DrawInternal(HDC hdc, int x, int y, int sizeX, int sizeY) { if (m_bmp == NULL) return; HDC hdcImg = CreateCompatibleDC(hdc); HBITMAP oldBmp = (HBITMAP)SelectObject(hdcImg, m_bmp); BITMAP bm; GetObject(m_bmp, sizeof(bm), &bm); if (bm.bmBitsPixel == 32) { BLENDFUNCTION bf = { 0 }; bf.SourceConstantAlpha = 255; bf.AlphaFormat = AC_SRC_ALPHA; GdiAlphaBlend(hdc, x, y, sizeX, sizeY, hdcImg, 0, 0, bm.bmWidth, bm.bmHeight, bf); } else BitBlt(hdc, x, y, sizeX, sizeY, hdcImg, 0, 0, SRCCOPY); SelectObject(hdcImg, oldBmp); DeleteDC(hdcImg); }
/** * content renderer for the advanced side bar button layout. includes * avatars */ void __fastcall CSideBar::m_AdvancedContentRenderer(const HDC hdc, const RECT *rcBox, const CSideBarButton *item) { const TWindowData *dat = item->getDat(); UINT id = item->getID(); LONG cx = rcBox->right - rcBox->left; LONG cy = rcBox->bottom - rcBox->top; SIZE szFirstLine, szSecondLine; if (id == IDC_SIDEBARUP || id == IDC_SIDEBARDOWN) m_DefaultContentRenderer(hdc, rcBox, item); else if (dat) { RECT rc = *rcBox; if (dat->ace && dat->ace->hbmPic) { // we have an avatar double dNewHeight, dNewWidth; LONG maxHeight = cy - 8; bool fFree = false; Utils::scaleAvatarHeightLimited(dat->ace->hbmPic, dNewWidth, dNewHeight, maxHeight); HBITMAP hbmResized = CSkin::ResizeBitmap(dat->ace->hbmPic, dNewWidth, dNewHeight, fFree); HDC dc = CreateCompatibleDC(hdc); HBITMAP hbmOld = reinterpret_cast<HBITMAP>(::SelectObject(dc, hbmResized)); LONG xOff = (cx - maxHeight) + (maxHeight - (LONG)dNewWidth) / 2 - 4; LONG yOff = (cy - (LONG)dNewHeight) / 2; GdiAlphaBlend(hdc, xOff, yOff, (LONG)dNewWidth, (LONG)dNewHeight, dc, 0, 0, (LONG)dNewWidth, (LONG)dNewHeight, CSkin::m_default_bf); ::SelectObject(dc, hbmOld); if (hbmResized != dat->ace->hbmPic) ::DeleteObject(hbmResized); ::DeleteDC(dc); rc.right -= (maxHeight + 6); } /* * calculate metrics based on font configuration. Determine if we have enough * space for both lines */ rc.left += 3; HFONT hOldFont = reinterpret_cast<HFONT>(::SelectObject(hdc, CInfoPanel::m_ipConfig.hFonts[IPFONTID_NICK])); ::GetTextExtentPoint32A(hdc, "A", 1, &szFirstLine); ::SelectObject(hdc, CInfoPanel::m_ipConfig.hFonts[IPFONTID_STATUS]); ::GetTextExtentPoint32A(hdc, "A", 1, &szSecondLine); szSecondLine.cy = max(szSecondLine.cy, 18); LONG required = szFirstLine.cy + szSecondLine.cy; bool fSecondLine = (required < cy ? true : false); DWORD dtFlags = DT_SINGLELINE | DT_WORD_ELLIPSIS | DT_END_ELLIPSIS | (!fSecondLine ? DT_VCENTER : 0); ::SelectObject(hdc, CInfoPanel::m_ipConfig.hFonts[IPFONTID_NICK]); rc.top++; ::SetBkMode(hdc, TRANSPARENT); CSkin::RenderText(hdc, dat->hThemeIP, dat->cache->getNick(), &rc, dtFlags, CSkin::m_glowSize, CInfoPanel::m_ipConfig.clrs[IPFONTID_NICK]); if (fSecondLine) { int iSize; HICON hIcon = dat->cache->getIcon(iSize); /* * TODO support larger icons at a later time. This side bar button * could use 32x32 icons as well. */ rc.top = rc.bottom - szSecondLine.cy - 2; ::DrawIconEx(hdc, rc.left, rc.top + (rc.bottom - rc.top) / 2 - 8, hIcon, 16, 16, 0, 0, DI_NORMAL); rc.left += 18; ::SelectObject(hdc, CInfoPanel::m_ipConfig.hFonts[IPFONTID_STATUS]); CSkin::RenderText(hdc, dat->hThemeIP, dat->szStatus, &rc, dtFlags | DT_VCENTER, CSkin::m_glowSize, CInfoPanel::m_ipConfig.clrs[IPFONTID_STATUS]); } ::SelectObject(hdc, hOldFont); } }
bool CBackground::FillBackground( const BITMAPFILEHEADER* apBkImgData, // Содержимое *.bmp файла LONG X, LONG Y, LONG Width, LONG Height, // Куда нужно положить картинку BackgroundOp Operation, // {eUpLeft = 0, eStretch = 1, eTile = 2, eUpRight = 4, ...} bool abFade) // затемнение картинки, когда ConEmu НЕ в фокусе { if (!hBgDc) return false; // Залить черным фоном RECT rcFull = MakeRect(X,Y,Width,Height); FillRect(hBgDc, &rcFull, (HBRUSH)GetStockObject(BLACK_BRUSH)); if (apBkImgData == NULL || apBkImgData->bfType != 0x4D42/*BM*/ || IsBadReadPtr(apBkImgData, apBkImgData->bfSize)) { return false; } bool lbRc = false; HDC hLoadDC = NULL; HBITMAP hLoadBmp = NULL; BITMAPINFO* pBmp = (BITMAPINFO*)(apBkImgData+1); LPBYTE pBits = ((LPBYTE)apBkImgData) + apBkImgData->bfOffBits; LPVOID pDstBits = NULL; BITMAPINFOHEADER* pHdr = &pBmp->bmiHeader; if (pHdr->biPlanes != 1 || pHdr->biCompression != BI_RGB) // BI_JPEG|BI_PNG { return false; } DWORD nBitSize = apBkImgData->bfSize - apBkImgData->bfOffBits; TODO("Stride?"); DWORD nCalcSize = (pHdr->biWidth * pHdr->biHeight * pHdr->biBitCount) >> 3; if (nBitSize > nCalcSize) nBitSize = nCalcSize; if (!gpSet->isFadeInactive) abFade = false; // Создать MemoryDC const HDC hScreenDC = GetDC(ghWnd); if (hScreenDC) { hLoadDC = CreateCompatibleDC(hScreenDC); ReleaseDC(ghWnd, hScreenDC); if (hLoadDC) { hLoadBmp = CreateDIBSection(hLoadDC, pBmp, DIB_RGB_COLORS, &pDstBits, NULL, 0); if (hLoadBmp && pDstBits) { // Поместить биты из apBkImgData в hLoadDC HBITMAP hOldLoadBmp = (HBITMAP)SelectObject(hLoadDC, hLoadBmp); memmove(pDstBits, pBits, nBitSize); GdiFlush(); // Гарантировать commit битов // Теперь - скопировать биты из hLoadDC в hBgDc с учетом положения и Operation BLENDFUNCTION bf = {AC_SRC_OVER, 0, gpSet->bgImageDarker, 0}; if (abFade) { // GetFadeColor возвращает ColorRef, поэтому при вызове для (0..255) // он должен вернуть "коэффициент" затемнения или осветления DWORD nHigh = (gpSet->GetFadeColor(255) & 0xFF); if (nHigh < 255) { // Затемнение фона bf.SourceConstantAlpha = LOBYTE(nHigh * bf.SourceConstantAlpha / 255); } //// "коэффициент" вернется в виде RGB (R==G==B) //DWORD nLow = gpSet->GetFadeColor(0); //if (nLow > 0 && ((nLow & 0xFF) < nHigh)) //{ // // Осветление фона // RECT r = {X,Y,X+Width,Y+Height}; // HBRUSH h = CreateSolidBrush(nLow); // FillRect(hBgDc, &r, h); // DeleteObject(h); // // еще нужно убедиться, что сама картинка будет немного прозрачной, // // чтобы это осветление было заметно // if ((nLow & 0xFF) < 200) // bf.SourceConstantAlpha = klMin((int)bf.SourceConstantAlpha, (int)(255 - (nLow & 0xFF))); // else if (bf.SourceConstantAlpha >= 240) // bf.SourceConstantAlpha = 240; //} } if ((Operation == eUpLeft) || (Operation == eUpRight) || (Operation == eDownLeft) || (Operation == eDownRight) || (Operation == eCenter)) { int W = klMin(Width,pHdr->biWidth); int H = klMin(Height,pHdr->biHeight); if (GdiAlphaBlend(hBgDc, X, Y, W, H, hLoadDC, 0, 0, W, H, bf)) lbRc = true; } else if (Operation == eStretch || Operation == eFit) { if (GdiAlphaBlend(hBgDc, X, Y, Width, Height, hLoadDC, 0, 0, pHdr->biWidth, pHdr->biHeight, bf)) lbRc = true; } else if (Operation == eFill) { int srcX = 0, srcY = 0, srcW = pHdr->biWidth, srcH = pHdr->biHeight; if (Width && Width > Height) { srcH = klMin((srcW * Height / Width), _abs(pHdr->biHeight)); srcY = (pHdr->biHeight - srcH) / 2; } else if (Height) { srcW = klMin((srcH * Width / Height), pHdr->biWidth); srcX = (pHdr->biWidth - srcW) / 2; } if (GdiAlphaBlend(hBgDc, X, Y, Width, Height, hLoadDC, srcX, srcY, srcW, srcH, bf)) lbRc = true; } else if (Operation == eTile) { for (int DY = Y; DY < (Y+Height); DY += pHdr->biHeight) { for (int DX = X; DX < (X+Width); DX += pHdr->biWidth) { int W = klMin((Width-DX),pHdr->biWidth); int H = klMin((Height-DY),pHdr->biHeight); if (GdiAlphaBlend(hBgDc, DX, DY, W, H, hLoadDC, 0, 0, W, H, bf)) lbRc = true; } } } _ASSERTE(lbRc && "GdiAlphaBlend failed in background creation?"); TODO("Осветление картинки в Fade, когда gpSet->mn_FadeLow>0"); //if (abFade) //{ // // "коэффициент" вернется в виде RGB (R==G==B) // DWORD nLow = gpSet->GetFadeColor(0); // if (nLow) // { // // Осветление фона // RECT r = {X,Y,X+Width,Y+Height}; // HBRUSH h = CreateSolidBrush(nLow); // // Осветлить картинку // //FillRect(hBgDc, &r, h); // DeleteObject(h); // } //} SelectObject(hLoadDC, hOldLoadBmp); } if (hLoadBmp) { DeleteObject(hLoadBmp); hLoadBmp = NULL; } DeleteDC(hLoadDC); hLoadDC = NULL; } } return lbRc; }
DWORD WINAPI ScriptThread(LPVOID p) { HWND hWnd=(HWND)p; HBRUSH brush; HBITMAP bmp; HDC hDC, hMemDC; RECT rect; SIZE size; int i,j,x,y,len; Sleep(100); hDC = GetDC(hWnd); hMemDC = CreateCompatibleDC( hDC ); GetClientRect(hWnd,&rect); bmp = CreateCompatibleBitmap(hDC, rect.right, rect.bottom); hFont = CreateFont( 30, 0, 0, 0, FW_THIN, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"MS Mincho" ); SelectObject(hDC, hFont); SelectObject(hMemDC, hFont); SelectObject(hMemDC, bmp); brush = CreateSolidBrush(RGB(0xFF,0xFF,0xFF)); FillRect(hMemDC,&rect,brush); FillRect(hDC,&rect,brush); TEXTMETRIC tm; GetTextMetrics(hDC,&tm); len=wcslen(str); size.cx=tm.tmMaxCharWidth*len; size.cy=tm.tmHeight+10; IthDrawText(hMemDC, str, len, 0, 0); ftn.SourceConstantAlpha=0x20; for (i=0;i<alpha_depth;i++) { if (!running) break; Sleep(100); GetClientRect(hWnd,&rect); GdiAlphaBlend(hDC, (rect.right-size.cx)>>1, (rect.bottom-size.cy)>>1, size.cx, size.cy, hMemDC, 0, 0, size.cx, size.cy, ftn); UpdateWindow(hWnd); } FillRect(hMemDC,&rect,brush); for (i=0;i<alpha_depth;i++) { if (!running) break; Sleep(100); GdiAlphaBlend(hDC, (rect.right-size.cx)>>1, (rect.bottom-size.cy)>>1, size.cx, size.cy, hMemDC, 0, 0, size.cx, size.cy, ftn); UpdateWindow(hWnd); } FillRect(hDC,&rect,brush); SelectObject(hMemDC,hFont); for (i=0;i<sentence_count;i++) { len=wcslen(text[i]); size.cx=len*tm.tmMaxCharWidth; size.cy=tm.tmHeight+10; HBITMAP text_bmp=CreateCompatibleBitmap(hDC, size.cx, size.cy); RECT r={0,0,size.cx, size.cy}; SelectObject(hMemDC,text_bmp); FillRect(hMemDC,&r,brush); IthDrawText(hMemDC,text[i],len,0,0); j=0; y=0; x=0; click=0; while (len>char_per_line) { size.cx=char_per_line*tm.tmMaxCharWidth; len-=char_per_line; j=20; while (j<size.cx) { if (click) break; GdiAlphaBlend(hDC, 0, y, j, size.cy, hMemDC, x, 0, j, size.cy, ftn); Sleep(20); j+=20; } BitBlt(hDC,0, y, size.cx, size.cy, hMemDC, x, 0, SRCCOPY); y+=size.cy; x+=size.cx; } size.cx=len*tm.tmMaxCharWidth; j=20; while (j<size.cx) { if (click) break; GdiAlphaBlend(hDC, 0, y, j, size.cy, hMemDC, x, 0, j, size.cy, ftn); Sleep(20); j+=20; } BitBlt(hDC,0, y, size.cx, size.cy, hMemDC, x, 0, SRCCOPY); y+=size.cy; UpdateWindow(hWnd); SelectObject(hMemDC,bmp); DeleteObject(text_bmp); ResetEvent(hClickEvent); WaitForSingleObject(hClickEvent,-1); ResetEvent(hClickEvent); FillRect(hDC,&rect,brush); } DeleteDC(hMemDC); ReleaseDC(hWnd, hDC); DeleteObject(bmp); MessageBox(0,L"Script over.",L"Over",0); return 0; }
static INT_PTR CALLBACK PhotoDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { const unsigned long iPageId = 3; TCHAR szAvatarFileName[MAX_PATH], szTempPath[MAX_PATH], szTempFileName[MAX_PATH]; PhotoDlgProcData* dat = (PhotoDlgProcData*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); switch (msg) { case WM_INITDIALOG: if (!lParam) break; // Launched from userinfo TranslateDialogDefault(hwndDlg); SendDlgItemMessage(hwndDlg, IDC_LOAD, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadImage(hInst, MAKEINTRESOURCE(IDI_OPEN), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0)); SendDlgItemMessage(hwndDlg, IDC_LOAD, BUTTONSETASFLATBTN, TRUE, 0); SendDlgItemMessage(hwndDlg, IDC_DELETE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadImage(hInst, MAKEINTRESOURCE(IDI_DELETE), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), 0)); SendDlgItemMessage(hwndDlg, IDC_DELETE, BUTTONSETASFLATBTN, TRUE, 0); ShowWindow(GetDlgItem(hwndDlg, IDC_SAVE), SW_HIDE); { dat = new PhotoDlgProcData; dat->ppro = (CJabberProto*)lParam; dat->hBitmap = NULL; dat->ppro->m_bPhotoChanged = FALSE; SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)dat); dat->ppro->WindowSubscribe(hwndDlg); } SendMessage(hwndDlg, WM_JABBER_REFRESH_VCARD, 0, 0); break; case WM_JABBER_REFRESH_VCARD: if (dat->hBitmap) { DeleteObject(dat->hBitmap); dat->hBitmap = NULL; DeleteFile(dat->ppro->m_szPhotoFileName); dat->ppro->m_szPhotoFileName[0] = '\0'; } EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), FALSE); dat->ppro->GetAvatarFileName(NULL, szAvatarFileName, _countof(szAvatarFileName)); if (_taccess(szAvatarFileName, 0) == 0) { if (GetTempPath(_countof(szTempPath), szTempPath) <= 0) mir_tstrcpy(szTempPath, _T(".\\")); if (GetTempFileName(szTempPath, _T("jab"), 0, szTempFileName) > 0) { dat->ppro->debugLog(_T("Temp file = %s"), szTempFileName); if (CopyFile(szAvatarFileName, szTempFileName, FALSE) == TRUE) { if ((dat->hBitmap = Bitmap_Load(szTempFileName)) != NULL) { FIP->FI_Premultiply(dat->hBitmap); mir_tstrcpy(dat->ppro->m_szPhotoFileName, szTempFileName); EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), TRUE); } else DeleteFile(szTempFileName); } else DeleteFile(szTempFileName); } } dat->ppro->m_bPhotoChanged = FALSE; InvalidateRect(hwndDlg, NULL, TRUE); UpdateWindow(hwndDlg); break; case WM_JABBER_CHANGED: dat->ppro->SetServerVcard(dat->ppro->m_bPhotoChanged, dat->ppro->m_szPhotoFileName); break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_DELETE: if (dat->hBitmap) { DeleteObject(dat->hBitmap); dat->hBitmap = NULL; DeleteFile(dat->ppro->m_szPhotoFileName); dat->ppro->m_szPhotoFileName[0] = '\0'; dat->ppro->m_bPhotoChanged = TRUE; EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), FALSE); InvalidateRect(hwndDlg, NULL, TRUE); UpdateWindow(hwndDlg); dat->ppro->m_vCardUpdates |= (1UL << iPageId); SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); } break; case IDC_LOAD: TCHAR szFilter[512], szFileName[MAX_PATH]; Bitmap_GetFilter(szFilter, _countof(szFilter)); OPENFILENAME ofn = { 0 }; ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hwndDlg; ofn.lpstrFilter = szFilter; ofn.lpstrCustomFilter = NULL; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_FILEMUSTEXIST | OFN_DONTADDTORECENT; szFileName[0] = '\0'; if (GetOpenFileName(&ofn)) { struct _stat st; HBITMAP hNewBitmap; dat->ppro->debugLog(_T("File selected is %s"), szFileName); if (_tstat(szFileName, &st) < 0 || st.st_size > 40 * 1024) { MessageBox(hwndDlg, TranslateT("Only JPG, GIF, and BMP image files smaller than 40 KB are supported."), TranslateT("Jabber vCard"), MB_OK | MB_SETFOREGROUND); break; } if (GetTempPath(_countof(szTempPath), szTempPath) <= 0) mir_tstrcpy(szTempPath, _T(".\\")); if (GetTempFileName(szTempPath, _T("jab"), 0, szTempFileName) > 0) { dat->ppro->debugLog(_T("Temp file = %s"), szTempFileName); if (CopyFile(szFileName, szTempFileName, FALSE) == TRUE) { if ((hNewBitmap = Bitmap_Load(szTempFileName)) != NULL) { if (dat->hBitmap) { DeleteObject(dat->hBitmap); DeleteFile(dat->ppro->m_szPhotoFileName); } dat->hBitmap = hNewBitmap; mir_tstrcpy(dat->ppro->m_szPhotoFileName, szTempFileName); dat->ppro->m_bPhotoChanged = TRUE; EnableWindow(GetDlgItem(hwndDlg, IDC_DELETE), TRUE); InvalidateRect(hwndDlg, NULL, TRUE); UpdateWindow(hwndDlg); dat->ppro->m_vCardUpdates |= (1UL << iPageId); SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); } else DeleteFile(szTempFileName); } else DeleteFile(szTempFileName); } } break; } break; case WM_PAINT: if (dat->hBitmap) { BITMAP bm; POINT ptSize, ptOrg, pt, ptFitSize; RECT rect; HWND hwndCanvas = GetDlgItem(hwndDlg, IDC_CANVAS); HDC hdcCanvas = GetDC(hwndCanvas); HDC hdcMem = CreateCompatibleDC(hdcCanvas); SelectObject(hdcMem, dat->hBitmap); SetMapMode(hdcMem, GetMapMode(hdcCanvas)); GetObject(dat->hBitmap, sizeof(BITMAP), (LPVOID)&bm); ptSize.x = bm.bmWidth; ptSize.y = bm.bmHeight; DPtoLP(hdcCanvas, &ptSize, 1); ptOrg.x = ptOrg.y = 0; DPtoLP(hdcMem, &ptOrg, 1); GetClientRect(hwndCanvas, &rect); InvalidateRect(hwndCanvas, NULL, TRUE); UpdateWindow(hwndCanvas); if (ptSize.x <= rect.right && ptSize.y <= rect.bottom) { pt.x = (rect.right - ptSize.x) / 2; pt.y = (rect.bottom - ptSize.y) / 2; ptFitSize = ptSize; } else { if (((float)(ptSize.x - rect.right)) / ptSize.x > ((float)(ptSize.y - rect.bottom)) / ptSize.y) { ptFitSize.x = rect.right; ptFitSize.y = (ptSize.y*rect.right) / ptSize.x; pt.x = 0; pt.y = (rect.bottom - ptFitSize.y) / 2; } else { ptFitSize.x = (ptSize.x*rect.bottom) / ptSize.y; ptFitSize.y = rect.bottom; pt.x = (rect.right - ptFitSize.x) / 2; pt.y = 0; } } RECT rc; GetClientRect(hwndCanvas, &rc); if (IsThemeActive()) DrawThemeParentBackground(hwndCanvas, hdcCanvas, &rc); else FillRect(hdcCanvas, &rc, (HBRUSH)GetSysColorBrush(COLOR_BTNFACE)); if (bm.bmBitsPixel == 32) { BLENDFUNCTION bf = { 0 }; bf.AlphaFormat = AC_SRC_ALPHA; bf.BlendOp = AC_SRC_OVER; bf.SourceConstantAlpha = 255; GdiAlphaBlend(hdcCanvas, pt.x, pt.y, ptFitSize.x, ptFitSize.y, hdcMem, ptOrg.x, ptOrg.y, ptSize.x, ptSize.y, bf); } else { SetStretchBltMode(hdcCanvas, COLORONCOLOR); StretchBlt(hdcCanvas, pt.x, pt.y, ptFitSize.x, ptFitSize.y, hdcMem, ptOrg.x, ptOrg.y, ptSize.x, ptSize.y, SRCCOPY); } DeleteDC(hdcMem); } break; case WM_NOTIFY: if (((LPNMHDR)lParam)->idFrom == 0) { switch (((LPNMHDR)lParam)->code) { case PSN_PARAMCHANGED: SendMessage(hwndDlg, WM_INITDIALOG, 0, ((PSHNOTIFY*)lParam)->lParam); break; case PSN_APPLY: dat->ppro->m_vCardUpdates &= ~(1UL << iPageId); dat->ppro->SaveVcardToDB(hwndDlg, iPageId); if (!dat->ppro->m_vCardUpdates) dat->ppro->SetServerVcard(dat->ppro->m_bPhotoChanged, dat->ppro->m_szPhotoFileName); break; } } break; case WM_DESTROY: DestroyIcon((HICON)SendDlgItemMessage(hwndDlg, IDC_LOAD, BM_SETIMAGE, IMAGE_ICON, 0)); DestroyIcon((HICON)SendDlgItemMessage(hwndDlg, IDC_DELETE, BM_SETIMAGE, IMAGE_ICON, 0)); dat->ppro->WindowUnsubscribe(hwndDlg); if (dat->hBitmap) { dat->ppro->debugLogA("Delete bitmap"); DeleteObject(dat->hBitmap); DeleteFile(dat->ppro->m_szPhotoFileName); } delete dat; break; } return FALSE; }