reactos/base/applications/mspaint/main.cpp
Katayama Hirofumi MZ 3e23cdf9ee
[MSPAINT] Some bug fixes on loading/saving files (#5385)
- Display a correct error message on failing to save a file.
- Don't confuse the main file info and the non-main file info.
- Rename ShowFileLoadError as ShowError, and strengthen and move it to dialogs.cpp.
- Add SetFileInfo and InitializeImage helper functions.
- Add IDS_SAVEERROR resource string.
- Modify SaveDIBToFile, SetBitmapAndInfo, and DoLoadImageFile functions.
CORE-18867
2023-07-05 12:06:22 +09:00

244 lines
7.1 KiB
C++

/*
* PROJECT: PAINT for ReactOS
* LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
* PURPOSE: Initializing everything
* COPYRIGHT: Copyright 2015 Benedikt Freisen <b.freisen@gmx.net>
*/
#include "precomp.h"
POINT g_ptStart, g_ptEnd;
BOOL g_askBeforeEnlarging = FALSE; // TODO: initialize from registry
HINSTANCE g_hinstExe = NULL;
TCHAR g_szFileName[MAX_LONG_PATH] = { 0 };
BOOL g_isAFile = FALSE;
BOOL g_imageSaved = FALSE;
BOOL g_showGrid = FALSE;
CMainWindow mainWindow;
/* FUNCTIONS ********************************************************/
// get file name extension from filter string
static BOOL
FileExtFromFilter(LPTSTR pExt, OPENFILENAME *pOFN)
{
LPTSTR pchExt = pExt;
*pchExt = 0;
DWORD nIndex = 1;
for (LPCTSTR pch = pOFN->lpstrFilter; *pch; ++nIndex)
{
pch += lstrlen(pch) + 1;
if (pOFN->nFilterIndex == nIndex)
{
for (++pch; *pch && *pch != _T(';'); ++pch)
{
*pchExt++ = *pch;
}
*pchExt = 0;
CharLower(pExt);
return TRUE;
}
pch += lstrlen(pch) + 1;
}
return FALSE;
}
// Hook procedure for OPENFILENAME to change the file name extension
static UINT_PTR APIENTRY
OFNHookProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HWND hParent;
OFNOTIFY *pon;
switch (uMsg)
{
case WM_NOTIFY:
pon = (OFNOTIFY *)lParam;
if (pon->hdr.code == CDN_TYPECHANGE)
{
hParent = GetParent(hwnd);
TCHAR Path[MAX_PATH];
SendMessage(hParent, CDM_GETFILEPATH, _countof(Path), (LPARAM)Path);
FileExtFromFilter(PathFindExtension(Path), pon->lpOFN);
SendMessage(hParent, CDM_SETCONTROLTEXT, 0x047c, (LPARAM)PathFindFileName(Path));
lstrcpyn(pon->lpOFN->lpstrFile, Path, pon->lpOFN->nMaxFile);
}
break;
}
return 0;
}
BOOL CMainWindow::GetOpenFileName(IN OUT LPTSTR pszFile, INT cchMaxFile)
{
static OPENFILENAME ofn = { 0 };
static CString strFilter;
if (ofn.lStructSize == 0)
{
// The "All Files" item text
CString strAllPictureFiles;
strAllPictureFiles.LoadString(g_hinstExe, IDS_ALLPICTUREFILES);
// Get the import filter
CSimpleArray<GUID> aguidFileTypesI;
CImage::GetImporterFilterString(strFilter, aguidFileTypesI, strAllPictureFiles,
CImage::excludeDefaultLoad, _T('\0'));
// Initializing the OPENFILENAME structure for GetOpenFileName
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = m_hWnd;
ofn.hInstance = g_hinstExe;
ofn.lpstrFilter = strFilter;
ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY;
ofn.lpstrDefExt = L"png";
}
ofn.lpstrFile = pszFile;
ofn.nMaxFile = cchMaxFile;
return ::GetOpenFileName(&ofn);
}
BOOL CMainWindow::GetSaveFileName(IN OUT LPTSTR pszFile, INT cchMaxFile)
{
static OPENFILENAME sfn = { 0 };
static CString strFilter;
if (sfn.lStructSize == 0)
{
// Get the export filter
CSimpleArray<GUID> aguidFileTypesE;
CImage::GetExporterFilterString(strFilter, aguidFileTypesE, NULL,
CImage::excludeDefaultSave, _T('\0'));
// Initializing the OPENFILENAME structure for GetSaveFileName
ZeroMemory(&sfn, sizeof(sfn));
sfn.lStructSize = sizeof(sfn);
sfn.hwndOwner = m_hWnd;
sfn.hInstance = g_hinstExe;
sfn.lpstrFilter = strFilter;
sfn.Flags = OFN_EXPLORER | OFN_OVERWRITEPROMPT | OFN_ENABLEHOOK;
sfn.lpfnHook = OFNHookProc;
sfn.lpstrDefExt = L"png";
LPWSTR pchDotExt = PathFindExtensionW(pszFile);
if (*pchDotExt == UNICODE_NULL)
{
// Choose PNG
wcscat(pszFile, L".png");
for (INT i = 0; i < aguidFileTypesE.GetSize(); ++i)
{
if (aguidFileTypesE[i] == Gdiplus::ImageFormatPNG)
{
sfn.nFilterIndex = i + 1;
break;
}
}
}
}
sfn.lpstrFile = pszFile;
sfn.nMaxFile = cchMaxFile;
return ::GetSaveFileName(&sfn);
}
BOOL CMainWindow::ChooseColor(IN OUT COLORREF *prgbColor)
{
static CHOOSECOLOR choosecolor = { 0 };
static COLORREF custColors[16] =
{
0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff,
0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff
};
if (choosecolor.lStructSize == 0)
{
// Initializing the CHOOSECOLOR structure for ChooseColor
ZeroMemory(&choosecolor, sizeof(choosecolor));
choosecolor.lStructSize = sizeof(choosecolor);
choosecolor.hwndOwner = m_hWnd;
choosecolor.lpCustColors = custColors;
}
choosecolor.Flags = CC_RGBINIT;
choosecolor.rgbResult = *prgbColor;
if (!::ChooseColor(&choosecolor))
return FALSE;
*prgbColor = choosecolor.rgbResult;
return TRUE;
}
HWND CMainWindow::DoCreate()
{
::LoadString(g_hinstExe, IDS_DEFAULTFILENAME, g_szFileName, _countof(g_szFileName));
CString strTitle;
strTitle.Format(IDS_WINDOWTITLE, PathFindFileName(g_szFileName));
RECT& rc = registrySettings.WindowPlacement.rcNormalPosition;
return Create(HWND_DESKTOP, rc, strTitle, WS_OVERLAPPEDWINDOW, WS_EX_ACCEPTFILES);
}
// entry point
INT WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, INT nCmdShow)
{
#ifdef _DEBUG
// Report any memory leaks on exit
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
g_hinstExe = hInstance;
// Initialize common controls library
INITCOMMONCONTROLSEX iccx;
iccx.dwSize = sizeof(iccx);
iccx.dwICC = ICC_STANDARD_CLASSES | ICC_USEREX_CLASSES | ICC_BAR_CLASSES;
InitCommonControlsEx(&iccx);
// Load settings from registry
registrySettings.Load(nCmdShow);
// Create the main window
if (!mainWindow.DoCreate())
{
MessageBox(NULL, TEXT("Failed to create main window."), NULL, MB_ICONERROR);
return 1;
}
// Initialize imageModel
if (__argc < 2 || !DoLoadImageFile(mainWindow, __targv[1], TRUE))
InitializeImage(NULL, NULL, FALSE);
// Make the window visible on the screen
mainWindow.ShowWindow(registrySettings.WindowPlacement.showCmd);
// Load the access keys
HACCEL hAccel = ::LoadAccelerators(hInstance, MAKEINTRESOURCE(800));
// The message loop
MSG msg;
while (::GetMessage(&msg, NULL, 0, 0))
{
if (fontsDialog.IsWindow() && fontsDialog.IsDialogMessage(&msg))
continue;
if (::TranslateAccelerator(mainWindow, hAccel, &msg))
continue;
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
// Unload the access keys
::DestroyAcceleratorTable(hAccel);
// Write back settings to registry
registrySettings.Store();
// Return the value that PostQuitMessage() gave
return (INT)msg.wParam;
}