From 036206a1c36738584c8df57f6dcd76c725ae7f45 Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Wed, 29 Apr 2020 07:44:18 +0900 Subject: [PATCH] [MSPAINT] Refactor loading/saving image file (#2686) - Add DoLoadImageFile, CreateWhiteDIB, and CMainWindow::ConfirmSave functions. - Replace LoadDIBFromFile function with DoLoadImageFile. - Fix the empty file loading. - Delete UpdateApplicationProperties function. - Rewrite SaveDIBToFile function. CORE-16982, CORE-16979 --- base/applications/mspaint/dib.cpp | 172 +++++++++++++++++++------- base/applications/mspaint/dib.h | 8 +- base/applications/mspaint/globalvar.h | 1 + base/applications/mspaint/history.cpp | 3 +- base/applications/mspaint/history.h | 2 - base/applications/mspaint/main.cpp | 63 +--------- base/applications/mspaint/winproc.cpp | 160 +++++++----------------- base/applications/mspaint/winproc.h | 2 +- 8 files changed, 186 insertions(+), 225 deletions(-) diff --git a/base/applications/mspaint/dib.cpp b/base/applications/mspaint/dib.cpp index ce74c093bd8..58c4c83e82f 100644 --- a/base/applications/mspaint/dib.cpp +++ b/base/applications/mspaint/dib.cpp @@ -26,6 +26,29 @@ CreateDIBWithProperties(int width, int height) return CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, NULL, NULL, 0); } +HBITMAP +CreateColorDIB(int width, int height, COLORREF rgb) +{ + HBITMAP ret = CreateDIBWithProperties(width, height); + if (!ret) + return NULL; + + if (rgb) + { + HDC hdc = CreateCompatibleDC(NULL); + HGDIOBJ hbmOld = SelectObject(hdc, ret); + RECT rc; + SetRect(&rc, 0, 0, width, height); + HBRUSH hbr = CreateSolidBrush(rgb); + FillRect(hdc, &rc, hbr); + DeleteObject(hbr); + SelectObject(hdc, hbmOld); + DeleteDC(hdc); + } + + return ret; +} + int GetDIBWidth(HBITMAP hBitmap) { @@ -42,35 +65,32 @@ GetDIBHeight(HBITMAP hBitmap) return bm.bmHeight; } -void -SaveDIBToFile(HBITMAP hBitmap, LPTSTR FileName, HDC hDC, LPSYSTEMTIME time, int *size, int hRes, int vRes) +BOOL SaveDIBToFile(HBITMAP hBitmap, LPTSTR FileName, HDC hDC) { CImage img; img.Attach(hBitmap); img.Save(FileName); // TODO: error handling img.Detach(); + WIN32_FIND_DATA find; + HANDLE hFind = FindFirstFile(FileName, &find); + if (hFind == INVALID_HANDLE_VALUE) + return FALSE; + FindClose(hFind); + // update time and size - - HANDLE hFile = - CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); - if (hFile == INVALID_HANDLE_VALUE) - return; - - if (time) - { - FILETIME ft; - GetFileTime(hFile, NULL, NULL, &ft); - FileTimeToSystemTime(&ft, time); - } - if (size) - *size = GetFileSize(hFile, NULL); + FILETIME ft; + FileTimeToLocalFileTime(&find.ftLastWriteTime, &ft); + FileTimeToSystemTime(&ft, &fileTime); + fileSize = find.nFileSizeLow; // TODO: update hRes and vRes - CloseHandle(hFile); - registrySettings.SetMostRecentFile(FileName); + + isAFile = TRUE; + imageSaved = TRUE; + return TRUE; } void ShowFileLoadError(LPCTSTR name) @@ -82,41 +102,105 @@ void ShowFileLoadError(LPCTSTR name) mainWindow.MessageBox(strText, strProgramName, MB_OK | MB_ICONEXCLAMATION); } -void -LoadDIBFromFile(HBITMAP * hBitmap, LPCTSTR name, LPSYSTEMTIME time, int *size, int *hRes, int *vRes) +HBITMAP SetBitmapAndInfo(HBITMAP hBitmap, LPCTSTR name, DWORD dwFileSize, BOOL isFile) { + if (hBitmap == NULL) + { + COLORREF white = RGB(255, 255, 255); + hBitmap = CreateColorDIB(registrySettings.BMPWidth, + registrySettings.BMPHeight, white); + if (hBitmap == NULL) + return FALSE; + + fileHPPM = fileVPPM = 2834; + ZeroMemory(&fileTime, sizeof(fileTime)); + } + else + { + // update PPMs + HDC hScreenDC = GetDC(NULL); + fileHPPM = (int)(GetDeviceCaps(hScreenDC, LOGPIXELSX) * 1000 / 25.4); + fileVPPM = (int)(GetDeviceCaps(hScreenDC, LOGPIXELSY) * 1000 / 25.4); + ReleaseDC(NULL, hScreenDC); + } + + // update image + imageModel.Insert(hBitmap); + imageModel.ClearHistory(); + + // update fileSize + fileSize = dwFileSize; + + // update filepathname + if (name && name[0]) + GetFullPathName(name, SIZEOF(filepathname), filepathname, NULL); + else + LoadString(hProgInstance, IDS_DEFAULTFILENAME, filepathname, SIZEOF(filepathname)); + + // set title + CString strTitle; + strTitle.Format(IDS_WINDOWTITLE, PathFindFileName(filepathname)); + mainWindow.SetWindowText(strTitle); + + // update file info and recent + isAFile = isFile; + if (isAFile) + registrySettings.SetMostRecentFile(filepathname); + + imageSaved = TRUE; + + return hBitmap; +} + +HBITMAP DoLoadImageFile(HWND hwnd, LPCTSTR name, BOOL fIsMainFile) +{ + // find the file + WIN32_FIND_DATA find; + HANDLE hFind = FindFirstFile(name, &find); + if (hFind == INVALID_HANDLE_VALUE) + { + // does not exist + CStringW strText; + strText.Format(IDS_LOADERRORTEXT, name); + MessageBoxW(hwnd, strText, NULL, MB_ICONERROR); + return NULL; + } + DWORD dwFileSize = find.nFileSizeLow; // get file size + FindClose(hFind); + + // is file empty? + if (dwFileSize == 0) + { + if (fIsMainFile) + { + FILETIME ft; + FileTimeToLocalFileTime(&find.ftLastWriteTime, &ft); + FileTimeToSystemTime(&ft, &fileTime); + return SetBitmapAndInfo(NULL, name, dwFileSize, TRUE); + } + } + + // load the image CImage img; img.Load(name); - *hBitmap = img.Detach(); + HBITMAP hBitmap = img.Detach(); - if (!hBitmap) + if (hBitmap == NULL) { - ShowFileLoadError(name); - return; + // cannot open + CStringW strText; + strText.Format(IDS_LOADERRORTEXT, name); + MessageBoxW(hwnd, strText, NULL, MB_ICONERROR); + return NULL; } - // update time and size - HANDLE hFile = - CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); - if (hFile == INVALID_HANDLE_VALUE) - { - ShowFileLoadError(name); - return; - } - - if (time) + if (fIsMainFile) { FILETIME ft; - GetFileTime(hFile, NULL, NULL, &ft); - FileTimeToSystemTime(&ft, time); + FileTimeToLocalFileTime(&find.ftLastWriteTime, &ft); + FileTimeToSystemTime(&ft, &fileTime); + SetBitmapAndInfo(hBitmap, name, dwFileSize, TRUE); } - if (size) - *size = GetFileSize(hFile, NULL); - HDC hScreenDC = GetDC(NULL); - *hRes = (int)(GetDeviceCaps(hScreenDC, LOGPIXELSX) * 1000 / 25.4); - *vRes = (int)(GetDeviceCaps(hScreenDC, LOGPIXELSY) * 1000 / 25.4); - ReleaseDC(NULL, hScreenDC); - - CloseHandle(hFile); + return hBitmap; } diff --git a/base/applications/mspaint/dib.h b/base/applications/mspaint/dib.h index 743c2e8e6ad..6bbb56d9c6d 100644 --- a/base/applications/mspaint/dib.h +++ b/base/applications/mspaint/dib.h @@ -9,14 +9,16 @@ #pragma once HBITMAP CreateDIBWithProperties(int width, int height); +HBITMAP CreateColorDIB(int width, int height, COLORREF rgb); int GetDIBWidth(HBITMAP hbm); int GetDIBHeight(HBITMAP hbm); -void SaveDIBToFile(HBITMAP hBitmap, LPTSTR FileName, HDC hDC, LPSYSTEMTIME time, int *size, int hRes, - int vRes); +BOOL SaveDIBToFile(HBITMAP hBitmap, LPTSTR FileName, HDC hDC); -void LoadDIBFromFile(HBITMAP *hBitmap, LPCTSTR name, LPSYSTEMTIME time, int *size, int *hRes, int *vRes); +HBITMAP DoLoadImageFile(HWND hwnd, LPCTSTR name, BOOL fIsMainFile); void ShowFileLoadError(LPCTSTR name); + +HBITMAP SetBitmapAndInfo(HBITMAP hBitmap, LPCTSTR name, DWORD dwFileSize, BOOL isFile); diff --git a/base/applications/mspaint/globalvar.h b/base/applications/mspaint/globalvar.h index ab42977518d..cd427c86b05 100644 --- a/base/applications/mspaint/globalvar.h +++ b/base/applications/mspaint/globalvar.h @@ -53,6 +53,7 @@ extern HINSTANCE hProgInstance; extern TCHAR filepathname[1000]; extern BOOL isAFile; +extern BOOL imageSaved; extern int fileSize; extern int fileHPPM; extern int fileVPPM; diff --git a/base/applications/mspaint/history.cpp b/base/applications/mspaint/history.cpp index abe03bf6318..b9f206cb165 100644 --- a/base/applications/mspaint/history.cpp +++ b/base/applications/mspaint/history.cpp @@ -161,8 +161,7 @@ void ImageModel::Crop(int nWidth, int nHeight, int nOffsetX, int nOffsetY) void ImageModel::SaveImage(LPTSTR lpFileName) { - SaveDIBToFile(hBms[currInd], lpFileName, hDrawingDC, &fileTime, &fileSize, fileHPPM, fileVPPM); - imageSaved = TRUE; + SaveDIBToFile(hBms[currInd], lpFileName, hDrawingDC); } BOOL ImageModel::IsImageSaved() diff --git a/base/applications/mspaint/history.h b/base/applications/mspaint/history.h index 7ed0409cfe1..1c5110f7306 100644 --- a/base/applications/mspaint/history.h +++ b/base/applications/mspaint/history.h @@ -21,8 +21,6 @@ private: int undoSteps; int redoSteps; public: - BOOL imageSaved; - ImageModel(); void CopyPrevious(void); void Undo(void); diff --git a/base/applications/mspaint/main.cpp b/base/applications/mspaint/main.cpp index 2b89afe9417..927eb7fa99f 100644 --- a/base/applications/mspaint/main.cpp +++ b/base/applications/mspaint/main.cpp @@ -51,6 +51,7 @@ HINSTANCE hProgInstance; TCHAR filepathname[1000]; BOOL isAFile = FALSE; +BOOL imageSaved = FALSE; int fileSize; int fileHPPM = 2834; int fileVPPM = 2834; @@ -252,67 +253,7 @@ _tWinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPTSTR lpszArgument if (__argc >= 2) { - WIN32_FIND_DATAW find; - HANDLE hFind = FindFirstFileW(__targv[1], &find); - if (hFind != INVALID_HANDLE_VALUE) - { - FindClose(hFind); - - // check the file size - if (find.nFileSizeHigh || find.nFileSizeLow) - { - // load it now - HBITMAP bmNew = NULL; - LoadDIBFromFile(&bmNew, __targv[1], &fileTime, &fileSize, &fileHPPM, &fileVPPM); - if (bmNew) - { - // valid bitmap file - GetFullPathName(__targv[1], SIZEOF(filepathname), filepathname, NULL); - imageModel.Insert(bmNew); - CPath pathFileName(filepathname); - pathFileName.StripPath(); - - CString strTitle; - strTitle.Format(IDS_WINDOWTITLE, (LPCTSTR)pathFileName); - mainWindow.SetWindowText(strTitle); - - imageModel.ClearHistory(); - - isAFile = TRUE; - registrySettings.SetMostRecentFile(filepathname); - } - else - { - // cannot open and not empty - CStringW strText; - strText.Format(IDS_LOADERRORTEXT, __targv[1]); - MessageBoxW(NULL, strText, NULL, MB_ICONERROR); - } - } - else - { - // open the empty file - GetFullPathName(__targv[1], SIZEOF(filepathname), filepathname, NULL); - CPath pathFileName(filepathname); - pathFileName.StripPath(); - - CString strTitle; - strTitle.Format(IDS_WINDOWTITLE, (LPCTSTR)pathFileName); - mainWindow.SetWindowText(strTitle); - - imageModel.ClearHistory(); - - isAFile = TRUE; - registrySettings.SetMostRecentFile(filepathname); - } - } - else - { - // does not exist - CStringW strText; - strText.Format(IDS_LOADERRORTEXT, __targv[1]); - MessageBoxW(NULL, strText, NULL, MB_ICONERROR); - } + DoLoadImageFile(mainWindow, __targv[1], TRUE); } /* initializing the CHOOSECOLOR structure for use with ChooseColor */ diff --git a/base/applications/mspaint/winproc.cpp b/base/applications/mspaint/winproc.cpp index 51ba366fe08..928c21b9e59 100644 --- a/base/applications/mspaint/winproc.cpp +++ b/base/applications/mspaint/winproc.cpp @@ -102,21 +102,6 @@ void CMainWindow::saveImage(BOOL overwrite) } } -void CMainWindow::UpdateApplicationProperties(HBITMAP bitmap, LPCTSTR newfilepathname) -{ - imageModel.Insert(bitmap); - CopyMemory(filepathname, newfilepathname, sizeof(filepathname)); - CPath pathFileName(newfilepathname); - pathFileName.StripPath(); - CString strTitle; - strTitle.Format(IDS_WINDOWTITLE, (LPCTSTR)pathFileName); - SetWindowText(strTitle); - imageModel.ClearHistory(); - isAFile = TRUE; - - registrySettings.SetMostRecentFile(newfilepathname); -} - void CMainWindow::InsertSelectionFromHBITMAP(HBITMAP bitmap, HWND window) { int width = GetDIBWidth(bitmap); @@ -174,17 +159,14 @@ void CMainWindow::InsertSelectionFromHBITMAP(HBITMAP bitmap, HWND window) LRESULT CMainWindow::OnDropFiles(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { - HDROP drophandle; TCHAR droppedfile[MAX_PATH]; - HBITMAP bmNew = NULL; - drophandle = (HDROP)wParam; - DragQueryFile(drophandle, 0, droppedfile, SIZEOF(droppedfile)); - DragFinish(drophandle); - LoadDIBFromFile(&bmNew, droppedfile, &fileTime, &fileSize, &fileHPPM, &fileVPPM); - if (bmNew != NULL) - { - UpdateApplicationProperties(bmNew, droppedfile); - } + + HDROP hDrop = (HDROP)wParam; + DragQueryFile(hDrop, 0, droppedfile, SIZEOF(droppedfile)); + DragFinish(hDrop); + + ConfirmSave() && DoLoadImageFile(m_hWnd, droppedfile, TRUE); + return 0; } @@ -202,29 +184,34 @@ LRESULT CMainWindow::OnDestroy(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH return 0; } +BOOL CMainWindow::ConfirmSave() +{ + if (imageModel.IsImageSaved()) + return TRUE; + + CString strProgramName; + strProgramName.LoadString(IDS_PROGRAMNAME); + + CString strSavePromptText; + strSavePromptText.Format(IDS_SAVEPROMPTTEXT, PathFindFileName(filepathname)); + + switch (MessageBox(strSavePromptText, strProgramName, MB_YESNOCANCEL | MB_ICONQUESTION)) + { + case IDYES: + saveImage(TRUE); + return imageModel.IsImageSaved(); + case IDNO: + return TRUE; + case IDCANCEL: + return FALSE; + } + + return TRUE; +} + LRESULT CMainWindow::OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { - if (!imageModel.IsImageSaved()) - { - CString strProgramName; - strProgramName.LoadString(IDS_PROGRAMNAME); - CPath pathFileName(filepathname); - pathFileName.StripPath(); - CString strSavePromptText; - strSavePromptText.Format(IDS_SAVEPROMPTTEXT, (LPCTSTR)pathFileName); - switch (MessageBox(strSavePromptText, strProgramName, MB_YESNOCANCEL | MB_ICONQUESTION)) - { - case IDNO: - DestroyWindow(); - break; - case IDYES: - saveImage(FALSE); - if (imageModel.IsImageSaved()) - DestroyWindow(); - break; - } - } - else + if (ConfirmSave()) { DestroyWindow(); } @@ -404,45 +391,15 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH SendMessage(WM_CLOSE, wParam, lParam); break; case IDM_FILENEW: - { - BOOL reset = TRUE; - if (!imageModel.IsImageSaved()) + if (ConfirmSave()) { - CString strProgramName; - strProgramName.LoadString(IDS_PROGRAMNAME); - CPath pathFileName(filepathname); - pathFileName.StripPath(); - CString strSavePromptText; - strSavePromptText.Format(IDS_SAVEPROMPTTEXT, (LPCTSTR)pathFileName); - switch (MessageBox(strSavePromptText, strProgramName, MB_YESNOCANCEL | MB_ICONQUESTION)) - { - case IDNO: - imageModel.imageSaved = TRUE; //TODO: move to ImageModel - break; - case IDYES: - saveImage(FALSE); - break; - case IDCANCEL: - reset = FALSE; - break; - } - } - if (reset && imageModel.IsImageSaved()) //TODO: move to ImageModel - { - imageModel.Clear(); - imageModel.ClearHistory(); + SetBitmapAndInfo(NULL, NULL, 0, FALSE); } break; - } case IDM_FILEOPEN: - if (GetOpenFileName(&ofn) != 0) + if (ConfirmSave() && GetOpenFileName(&ofn)) { - HBITMAP bmNew = NULL; - LoadDIBFromFile(&bmNew, ofn.lpstrFile, &fileTime, &fileSize, &fileHPPM, &fileVPPM); - if (bmNew != NULL) - { - UpdateApplicationProperties(bmNew, ofn.lpstrFile); - } + DoLoadImageFile(m_hWnd, ofn.lpstrFile, TRUE); } break; case IDM_FILESAVE: @@ -494,42 +451,22 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH break; case IDM_FILE1: { - HBITMAP bmNew = NULL; - LoadDIBFromFile(&bmNew, registrySettings.strFile1, &fileTime, &fileSize, &fileHPPM, &fileVPPM); - if (bmNew != NULL) - { - UpdateApplicationProperties(bmNew, registrySettings.strFile1); - } + ConfirmSave() && DoLoadImageFile(m_hWnd, registrySettings.strFile1, TRUE); break; } case IDM_FILE2: { - HBITMAP bmNew = NULL; - LoadDIBFromFile(&bmNew, registrySettings.strFile2, &fileTime, &fileSize, &fileHPPM, &fileVPPM); - if (bmNew != NULL) - { - UpdateApplicationProperties(bmNew, registrySettings.strFile2); - } + ConfirmSave() && DoLoadImageFile(m_hWnd, registrySettings.strFile2, TRUE); break; } case IDM_FILE3: { - HBITMAP bmNew = NULL; - LoadDIBFromFile(&bmNew, registrySettings.strFile3, &fileTime, &fileSize, &fileHPPM, &fileVPPM); - if (bmNew != NULL) - { - UpdateApplicationProperties(bmNew, registrySettings.strFile3); - } + ConfirmSave() && DoLoadImageFile(m_hWnd, registrySettings.strFile3, TRUE); break; } case IDM_FILE4: { - HBITMAP bmNew = NULL; - LoadDIBFromFile(&bmNew, registrySettings.strFile4, &fileTime, &fileSize, &fileHPPM, &fileVPPM); - if (bmNew != NULL) - { - UpdateApplicationProperties(bmNew, registrySettings.strFile4); - } + ConfirmSave() && DoLoadImageFile(m_hWnd, registrySettings.strFile4, TRUE); break; } case IDM_EDITUNDO: @@ -578,18 +515,17 @@ LRESULT CMainWindow::OnCommand(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bH break; } case IDM_EDITCOPYTO: - if (GetSaveFileName(&ofn) != 0) - SaveDIBToFile(selectionModel.GetBitmap(), ofn.lpstrFile, imageModel.GetDC(), NULL, NULL, fileHPPM, fileVPPM); + if (GetSaveFileName(&ofn)) + SaveDIBToFile(selectionModel.GetBitmap(), ofn.lpstrFile, imageModel.GetDC()); break; case IDM_EDITPASTEFROM: - if (GetOpenFileName(&ofn) != 0) + if (GetOpenFileName(&ofn)) { - HBITMAP bmNew = NULL; - LoadDIBFromFile(&bmNew, ofn.lpstrFile, &fileTime, &fileSize, &fileHPPM, &fileVPPM); - if (bmNew != NULL) + HBITMAP hbmNew = DoLoadImageFile(m_hWnd, ofn.lpstrFile, FALSE); + if (hbmNew) { - InsertSelectionFromHBITMAP(bmNew, m_hWnd); - DeleteObject(bmNew); + InsertSelectionFromHBITMAP(hbmNew, m_hWnd); + DeleteObject(hbmNew); } } break; diff --git a/base/applications/mspaint/winproc.h b/base/applications/mspaint/winproc.h index 6b212f619b0..0c4a4e799c9 100644 --- a/base/applications/mspaint/winproc.h +++ b/base/applications/mspaint/winproc.h @@ -42,6 +42,6 @@ public: void alignChildrenToMainWindow(); void saveImage(BOOL overwrite); - void UpdateApplicationProperties(HBITMAP bitmap, LPCTSTR newfilepathname); void InsertSelectionFromHBITMAP(HBITMAP bitmap, HWND window); + BOOL ConfirmSave(); };