From a3243c657c0c0fe229697aea5f4b2e111583e28c Mon Sep 17 00:00:00 2001 From: Takashi Sawanaka Date: Sun, 7 Jul 2019 21:14:21 +0900 Subject: [PATCH] Display WinMerge logo beautifully on HiDPI screen --- Src/AboutDlg.cpp | 8 +-- Src/Common/Bitmap.cpp | 22 ++++++ Src/Common/Bitmap.h | 2 + Src/Common/Picture.cpp | 141 --------------------------------------- Src/Common/Picture.h | 53 --------------- Src/Merge.vs2017.vcxproj | 4 +- Src/Merge.vs2017.vcxproj.filters | 6 -- Src/Merge.vs2019.vcxproj | 2 - Src/Merge.vs2019.vcxproj.filters | 6 -- Src/OpenView.cpp | 8 +-- Src/OpenView.h | 3 +- Src/StdAfx.h | 2 + 12 files changed, 36 insertions(+), 221 deletions(-) delete mode 100644 Src/Common/Picture.cpp delete mode 100644 Src/Common/Picture.h diff --git a/Src/AboutDlg.cpp b/Src/AboutDlg.cpp index 2050542c1..f43110b96 100644 --- a/Src/AboutDlg.cpp +++ b/Src/AboutDlg.cpp @@ -24,7 +24,7 @@ #include "stdafx.h" #include "AboutDlg.h" #include "TrDialogs.h" -#include "Picture.h" +#include "Bitmap.h" #include "resource.h" // IDD_ABOUTBOX /** @@ -63,7 +63,7 @@ public: private: CAboutDlg *m_p; - CPicture m_image; + ATL::CImage m_image; CFont m_font; }; @@ -98,7 +98,7 @@ BOOL CAboutDlg::Impl::OnInitDialog() { CTrDialog::OnInitDialog(); - m_image.Load(IDR_SPLASH); + LoadImageFromResource(m_image, MAKEINTRESOURCE(IDR_SPLASH), _T("IMAGE")); m_font.CreatePointFont(10 * 10, _T("Tahoma")); @@ -131,7 +131,7 @@ void CAboutDlg::Impl::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) { CRect rc; GetDlgItem(nIDCtl)->GetClientRect(&rc); - m_image.Render(CDC::FromHandle(lpDrawItemStruct->hDC), rc); + m_image.Draw(lpDrawItemStruct->hDC, rc, Gdiplus::InterpolationModeBicubic); } /** * @brief Show contributors list. diff --git a/Src/Common/Bitmap.cpp b/Src/Common/Bitmap.cpp index 0ceefe338..9e6c71888 100644 --- a/Src/Common/Bitmap.cpp +++ b/Src/Common/Bitmap.cpp @@ -183,4 +183,26 @@ bool GrayScale(CBitmap *pBitmap) else return false; return pBitmap->SetBitmapBits(nCount, pbuf.get()) != 0; +} + +bool LoadImageFromResource(ATL::CImage& image, const TCHAR *pName, const TCHAR *pType) +{ + HRSRC hrsrc = FindResource(nullptr, pName, pType); + if (hrsrc == nullptr) + return false; + DWORD dwResourceSize = SizeofResource(nullptr, hrsrc); + HGLOBAL hglbImage = LoadResource(nullptr, hrsrc); + if (hglbImage == nullptr) + return false; + LPVOID pvSourceResourceData = LockResource(hglbImage); + if (pvSourceResourceData == nullptr) + return false; + IStream * pStream = SHCreateMemStream(reinterpret_cast(pvSourceResourceData), dwResourceSize); + if (!pStream) + return false; + HRESULT hr = image.Load(pStream); + pStream->Release(); + if (FAILED(hr)) + return false; + return true; } \ No newline at end of file diff --git a/Src/Common/Bitmap.h b/Src/Common/Bitmap.h index cf15caf1f..ac16fc68a 100644 --- a/Src/Common/Bitmap.h +++ b/Src/Common/Bitmap.h @@ -9,8 +9,10 @@ class CBitmap; class CDC; class CRect; +namespace ATL { class CImage; } CBitmap *CopyRectToBitmap(CDC *pDC, const CRect & rect); void DrawBitmap(CDC *pDC, int x, int y, CBitmap *pBitmap); CBitmap *GetDarkenedBitmap(CDC *pDC, CBitmap *pBitmap); bool GrayScale(CBitmap *pBitmap); +bool LoadImageFromResource(ATL::CImage& image, const TCHAR *pName, const TCHAR *pType); diff --git a/Src/Common/Picture.cpp b/Src/Common/Picture.cpp deleted file mode 100644 index 96026e57f..000000000 --- a/Src/Common/Picture.cpp +++ /dev/null @@ -1,141 +0,0 @@ -//////////////////////////////////////////////////////////////// -// MSDN Magazine -- October 2001 -// If this code works, it was written by Paul DiLascia. -// If not, I don't know who wrote it. -// Compiles with Visual C++ 6.0 for Windows 98 and probably Windows 2000 too. -// Set tabsize = 3 in your editor. -// -#include "StdAfx.h" -#include "Picture.h" -#include - -#ifdef _DEBUG -#define new DEBUG_NEW -#endif - -//////////////////////////////////////////////////////////////// -// CPicture implementation -// - -CPicture::CPicture() : m_hr(S_OK) -{ -} - -CPicture::~CPicture() -{ -} - -////////////////// -// Load from resource. Looks for "IMAGE" type. -// -bool CPicture::Load(UINT nIDRes) -{ - // find resource in resource file - HINSTANCE hInst = AfxGetInstanceHandle(); - HRSRC hRsrc = ::FindResource(hInst, - MAKEINTRESOURCE(nIDRes), - TEXT("IMAGE")); // type - if (hRsrc == nullptr) - return false; - - // load resource into memory - DWORD len = SizeofResource(hInst, hRsrc); - BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc); - if (lpRsrc == nullptr) - return false; - - // create memory file and load it - CMemFile file(lpRsrc, len); - bool bRet = Load(file); - FreeResource(hRsrc); - - return bRet; -} - -////////////////// -// Load from path name. -// -bool CPicture::Load(LPCTSTR pszPathName) -{ - CFile file; - if (!file.Open(pszPathName, CFile::modeRead|CFile::shareDenyWrite)) - return false; - bool bRet = Load(file); - file.Close(); - return bRet; -} - -////////////////// -// Load from CFile -// -bool CPicture::Load(CFile& file) -{ - CArchive ar(&file, CArchive::load | CArchive::bNoFlushOnDelete); - return Load(ar); -} - -////////////////// -// Load from archive--create stream and load from stream. -// -// CArchiveStream Doesn't compile with VS2003.Net -bool CPicture::Load(CArchive& ar) -{ - CArchiveStream arcstream(&ar); - return Load((IStream*)&arcstream); -} - - -////////////////// -// Load from stream (IStream). This is the one that really does it: call -// OleLoadPicture to do the work. -// -bool CPicture::Load(IStream* pstm) -{ - Free(); - HRESULT hr = OleLoadPicture(pstm, 0, FALSE, - IID_IPicture, (void**)&m_spIPicture); - ASSERT(SUCCEEDED(hr) && m_spIPicture != nullptr); - return true; -} - -////////////////// -// Render to device context. Covert to HIMETRIC for IPicture. -// -bool CPicture::Render(CDC* pDC, CRect rc /*= CRect(0,0,0,0)*/, LPCRECT prcMFBounds /*= nullptr*/) const -{ - ASSERT(pDC != nullptr); - - if (rc.IsRectNull()) { - CSize sz = GetImageSize(pDC); - rc.right = sz.cx; - rc.bottom = sz.cy; - } - long hmWidth,hmHeight; // HIMETRIC units - GetHIMETRICSize(hmWidth, hmHeight); - m_spIPicture->Render(*pDC, rc.left, rc.top, rc.Width(), rc.Height(), - 0, hmHeight, hmWidth, -hmHeight, prcMFBounds); - - return true; -} - -////////////////// -// Get image size in pixels. Converts from HIMETRIC to device coords. -// -CSize CPicture::GetImageSize(CDC* pDC /*= nullptr*/) const -{ - if (m_spIPicture == nullptr) - return CSize(0,0); - - LONG hmWidth, hmHeight; // HIMETRIC units - if (FAILED(m_spIPicture->get_Width(&hmWidth)) || FAILED(m_spIPicture->get_Height(&hmHeight))) - return CSize(0, 0); - CSize sz(hmWidth,hmHeight); - if (pDC==nullptr) { - CWindowDC dc(nullptr); - dc.HIMETRICtoDP(&sz); // convert to pixels - } else { - pDC->HIMETRICtoDP(&sz); - } - return sz; -} - diff --git a/Src/Common/Picture.h b/Src/Common/Picture.h deleted file mode 100644 index 9387a7051..000000000 --- a/Src/Common/Picture.h +++ /dev/null @@ -1,53 +0,0 @@ -//////////////////////////////////////////////////////////////// -// MSDN Magazine -- October 2001 -// If this code works, it was written by Paul DiLascia. -// If not, I don't know who wrote it. -// Compiles with Visual C++ 6.0 for Windows 98 and probably Windows 2000 too. -// Set tabsize = 3 in your editor. -// -#pragma once -#include - -////////////////// -// Picture object--encapsulates IPicture -// -class CPicture { -public: - CPicture(); - ~CPicture(); - - // Load frm various sosurces - bool Load(UINT nIDRes); - bool Load(LPCTSTR pszPathName); - bool Load(CFile& file); - bool Load(CArchive& ar); - bool Load(IStream* pstm); - - // render to device context - bool Render(CDC* pDC, CRect rc=CRect(0,0,0,0), - LPCRECT prcMFBounds=nullptr) const; - - CSize GetImageSize(CDC* pDC=nullptr) const; - - operator IPicture*() { - return m_spIPicture; - } - - void GetHIMETRICSize(OLE_XSIZE_HIMETRIC& cx, OLE_YSIZE_HIMETRIC& cy) const { - cx = cy = 0; - const_cast(this)->m_hr = m_spIPicture->get_Width(&cx); - ASSERT(SUCCEEDED(m_hr)); - const_cast(this)->m_hr = m_spIPicture->get_Height(&cy); - ASSERT(SUCCEEDED(m_hr)); - } - - void Free() { - if (m_spIPicture) { - m_spIPicture.Release(); - } - } - -protected: - CComQIPtrm_spIPicture; // ATL smart pointer to IPicture - HRESULT m_hr; // last error code -}; diff --git a/Src/Merge.vs2017.vcxproj b/Src/Merge.vs2017.vcxproj index 68dc2d578..72377cf38 100644 --- a/Src/Merge.vs2017.vcxproj +++ b/Src/Merge.vs2017.vcxproj @@ -854,7 +854,6 @@ pch.h $(IntDir)$(TargetName)2.pch - Use pch.h @@ -1218,7 +1217,6 @@ - @@ -1340,4 +1338,4 @@ - + \ No newline at end of file diff --git a/Src/Merge.vs2017.vcxproj.filters b/Src/Merge.vs2017.vcxproj.filters index 3050bffd2..e8338f66f 100644 --- a/Src/Merge.vs2017.vcxproj.filters +++ b/Src/Merge.vs2017.vcxproj.filters @@ -475,9 +475,6 @@ MFCGui\Common\Source Files - - MFCGui\Common\Source Files - MFCGui\Common\Source Files @@ -1272,9 +1269,6 @@ MFCGui\Common\Header Files - - MFCGui\Common\Header Files - MFCGui\Common\Header Files diff --git a/Src/Merge.vs2019.vcxproj b/Src/Merge.vs2019.vcxproj index 31ff9c5f1..583d6f45f 100644 --- a/Src/Merge.vs2019.vcxproj +++ b/Src/Merge.vs2019.vcxproj @@ -853,7 +853,6 @@ pch.h $(IntDir)$(TargetName)2.pch - Use pch.h @@ -1217,7 +1216,6 @@ - diff --git a/Src/Merge.vs2019.vcxproj.filters b/Src/Merge.vs2019.vcxproj.filters index 3050bffd2..e8338f66f 100644 --- a/Src/Merge.vs2019.vcxproj.filters +++ b/Src/Merge.vs2019.vcxproj.filters @@ -475,9 +475,6 @@ MFCGui\Common\Source Files - - MFCGui\Common\Source Files - MFCGui\Common\Source Files @@ -1272,9 +1269,6 @@ MFCGui\Common\Header Files - - MFCGui\Common\Header Files - MFCGui\Common\Header Files diff --git a/Src/OpenView.cpp b/Src/OpenView.cpp index ce95200e9..eff5f5469 100644 --- a/Src/OpenView.cpp +++ b/Src/OpenView.cpp @@ -40,7 +40,7 @@ #include "FileOrFolderSelect.h" #include "7zCommon.h" #include "Constants.h" -#include "Picture.h" +#include "Bitmap.h" #include "DropHandler.h" #include "FileFilterHelper.h" #include "Plugins.h" @@ -177,7 +177,7 @@ void COpenView::OnInitialUpdate() theApp.TranslateDialog(m_hWnd); - if (!m_picture.Load(IDR_LOGO)) + if (!LoadImageFromResource(m_image, MAKEINTRESOURCE(IDR_LOGO), _T("IMAGE"))) return; CFormView::OnInitialUpdate(); @@ -319,9 +319,9 @@ void COpenView::OnPaint() GetClientRect(&rc); // Draw the logo image - CSize size = m_picture.GetImageSize(&dc); + CSize size{ m_image.GetWidth(), m_image.GetHeight() }; CRect rcImage(0, 0, size.cx * GetSystemMetrics(SM_CXSMICON) / 16, size.cy * GetSystemMetrics(SM_CYSMICON) / 16); - m_picture.Render(&dc, rcImage); + m_image.Draw(dc.m_hDC, rcImage, Gdiplus::InterpolationModeBicubic); // And extend it to the Right boundary dc.PatBlt(rcImage.Width(), 0, rc.Width() - rcImage.Width(), rcImage.Height(), PATCOPY); diff --git a/Src/OpenView.h b/Src/OpenView.h index be3504abb..7a1f5d512 100644 --- a/Src/OpenView.h +++ b/Src/OpenView.h @@ -31,7 +31,6 @@ #include "SuperComboBox.h" #include "FileTransform.h" #include "PathContext.h" -#include "Picture.h" #include "CMoveConstraint.h" #include "TrDialogs.h" #include @@ -87,7 +86,7 @@ public: private: String m_strBrowsePath[3]; /**< Left/middle/right path from browse dialog. */ CWinThread *m_pUpdateButtonStatusThread; - CPicture m_picture; /**< Image loader/viewer for logo image */ + ATL::CImage m_image; /**< Image loader/viewer for logo image */ CSize m_sizeOrig; prdlg::CMoveConstraint m_constraint; CFont m_fontSwapButton; diff --git a/Src/StdAfx.h b/Src/StdAfx.h index c125b139a..09fcabcfb 100644 --- a/Src/StdAfx.h +++ b/Src/StdAfx.h @@ -37,6 +37,8 @@ #include // MFC private declarations (crystal text needs but doesn't include this) #include // MFC OLE (COM) support +#include + // For CSizingControlBar #include "sizecbar.h" #include "scbarg.h" -- 2.11.0