2015-05-08 16:02:36 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: PAINT for ReactOS
|
|
|
|
* LICENSE: LGPL
|
2015-09-09 13:13:35 +00:00
|
|
|
* FILE: base/applications/mspaint/main.cpp
|
2015-05-08 16:02:36 +00:00
|
|
|
* PURPOSE: Initializing everything
|
|
|
|
* PROGRAMMERS: Benedikt Freisen
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
|
|
/* FUNCTIONS ********************************************************/
|
|
|
|
|
|
|
|
POINT start;
|
|
|
|
POINT last;
|
2015-07-07 11:15:24 +00:00
|
|
|
|
|
|
|
ToolsModel toolsModel;
|
|
|
|
|
2015-07-09 09:48:01 +00:00
|
|
|
SelectionModel selectionModel;
|
|
|
|
|
2015-07-07 11:15:24 +00:00
|
|
|
PaletteModel paletteModel;
|
2015-05-08 16:02:36 +00:00
|
|
|
|
2015-08-16 19:52:37 +00:00
|
|
|
RegistrySettings registrySettings;
|
|
|
|
|
2015-07-23 13:11:54 +00:00
|
|
|
ImageModel imageModel;
|
|
|
|
BOOL askBeforeEnlarging = FALSE; // TODO: initialize from registry
|
|
|
|
|
2015-05-08 16:02:36 +00:00
|
|
|
HWND hStatusBar;
|
|
|
|
CHOOSECOLOR choosecolor;
|
|
|
|
OPENFILENAME ofn;
|
|
|
|
OPENFILENAME sfn;
|
|
|
|
HICON hNontranspIcon;
|
|
|
|
HICON hTranspIcon;
|
|
|
|
|
|
|
|
HINSTANCE hProgInstance;
|
|
|
|
|
|
|
|
TCHAR filepathname[1000];
|
|
|
|
BOOL isAFile = FALSE;
|
2020-04-28 22:44:18 +00:00
|
|
|
BOOL imageSaved = FALSE;
|
2015-05-08 16:02:36 +00:00
|
|
|
int fileSize;
|
|
|
|
int fileHPPM = 2834;
|
|
|
|
int fileVPPM = 2834;
|
|
|
|
SYSTEMTIME fileTime;
|
|
|
|
|
|
|
|
BOOL showGrid = FALSE;
|
|
|
|
BOOL showMiniature = FALSE;
|
|
|
|
|
2015-07-07 10:42:49 +00:00
|
|
|
CMainWindow mainWindow;
|
2015-08-17 12:03:39 +00:00
|
|
|
CFullscreenWindow fullscreenWindow;
|
2015-07-07 11:02:30 +00:00
|
|
|
CMiniatureWindow miniature;
|
2015-07-07 11:44:50 +00:00
|
|
|
CToolBox toolBoxContainer;
|
2015-07-07 10:42:49 +00:00
|
|
|
CToolSettingsWindow toolSettingsWindow;
|
|
|
|
CPaletteWindow paletteWindow;
|
2023-03-16 22:45:14 +00:00
|
|
|
CCanvasWindow canvasWindow;
|
2015-07-07 10:42:49 +00:00
|
|
|
CSelectionWindow selectionWindow;
|
2015-07-07 11:02:30 +00:00
|
|
|
CImgAreaWindow imageArea;
|
2015-07-07 10:42:49 +00:00
|
|
|
CTextEditWindow textEditWindow;
|
2015-05-08 16:02:36 +00:00
|
|
|
|
2017-06-07 10:12:05 +00:00
|
|
|
// get file name extension from filter string
|
|
|
|
static BOOL
|
|
|
|
FileExtFromFilter(LPTSTR pExt, LPCTSTR pTitle, 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
|
2017-07-24 10:34:06 +00:00
|
|
|
static UINT_PTR APIENTRY
|
2017-06-07 10:12:05 +00:00
|
|
|
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];
|
2021-12-28 01:44:56 +00:00
|
|
|
SendMessage(hParent, CDM_GETFILEPATH, _countof(Path), (LPARAM)Path);
|
2017-06-07 10:12:05 +00:00
|
|
|
LPTSTR pchTitle = _tcsrchr(Path, _T('\\'));
|
|
|
|
if (pchTitle == NULL)
|
|
|
|
pchTitle = _tcsrchr(Path, _T('/'));
|
|
|
|
|
|
|
|
LPTSTR pch = _tcsrchr((pchTitle ? pchTitle : Path), _T('.'));
|
|
|
|
if (pch && pchTitle)
|
|
|
|
{
|
|
|
|
pchTitle++;
|
|
|
|
*pch = 0;
|
|
|
|
FileExtFromFilter(pch, pchTitle, pon->lpOFN);
|
|
|
|
SendMessage(hParent, CDM_SETCONTROLTEXT, 0x047c, (LPARAM)pchTitle);
|
2019-04-27 16:53:59 +00:00
|
|
|
lstrcpyn(pon->lpOFN->lpstrFile, Path, pon->lpOFN->nMaxFile);
|
2017-06-07 10:12:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-05-08 16:02:36 +00:00
|
|
|
/* entry point */
|
|
|
|
|
|
|
|
int WINAPI
|
2023-03-16 22:26:44 +00:00
|
|
|
_tWinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPTSTR lpszArgument, INT nCmdShow)
|
2015-05-08 16:02:36 +00:00
|
|
|
{
|
|
|
|
HWND hwnd; /* This is the handle for our window */
|
|
|
|
MSG messages; /* Here messages to the application are saved */
|
|
|
|
|
|
|
|
HMENU menu;
|
2016-10-01 20:04:43 +00:00
|
|
|
HACCEL haccel;
|
2015-05-08 16:02:36 +00:00
|
|
|
|
|
|
|
TCHAR sfnFilename[1000];
|
|
|
|
TCHAR sfnFiletitle[256];
|
|
|
|
TCHAR ofnFilename[1000];
|
|
|
|
TCHAR ofnFiletitle[256];
|
|
|
|
TCHAR miniaturetitle[100];
|
2019-12-23 19:11:33 +00:00
|
|
|
static COLORREF custColors[16] = {
|
|
|
|
0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff,
|
2015-05-08 16:02:36 +00:00
|
|
|
0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff
|
|
|
|
};
|
|
|
|
|
2023-03-13 22:17:14 +00:00
|
|
|
#ifdef _DEBUG
|
|
|
|
/* Report any memory leaks on exit */
|
|
|
|
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
|
|
|
|
#endif
|
|
|
|
|
2015-05-08 16:02:36 +00:00
|
|
|
hProgInstance = hThisInstance;
|
|
|
|
|
|
|
|
/* initialize common controls library */
|
2022-01-05 07:26:05 +00:00
|
|
|
INITCOMMONCONTROLSEX iccx;
|
|
|
|
iccx.dwSize = sizeof(iccx);
|
2022-01-09 14:24:30 +00:00
|
|
|
iccx.dwICC = ICC_STANDARD_CLASSES | ICC_USEREX_CLASSES | ICC_BAR_CLASSES;
|
2022-01-05 07:26:05 +00:00
|
|
|
InitCommonControlsEx(&iccx);
|
2015-05-08 16:02:36 +00:00
|
|
|
|
2021-12-28 01:44:56 +00:00
|
|
|
LoadString(hThisInstance, IDS_DEFAULTFILENAME, filepathname, _countof(filepathname));
|
2016-09-26 19:53:42 +00:00
|
|
|
CPath pathFileName(filepathname);
|
|
|
|
pathFileName.StripPath();
|
|
|
|
CString strTitle;
|
|
|
|
strTitle.Format(IDS_WINDOWTITLE, (LPCTSTR)pathFileName);
|
2021-12-28 01:44:56 +00:00
|
|
|
LoadString(hThisInstance, IDS_MINIATURETITLE, miniaturetitle, _countof(miniaturetitle));
|
2015-05-08 16:02:36 +00:00
|
|
|
|
2015-08-16 19:52:37 +00:00
|
|
|
/* load settings from registry */
|
2023-03-16 22:26:44 +00:00
|
|
|
registrySettings.Load(nCmdShow);
|
2015-08-16 19:52:37 +00:00
|
|
|
showMiniature = registrySettings.ShowThumbnail;
|
|
|
|
imageModel.Crop(registrySettings.BMPWidth, registrySettings.BMPHeight);
|
|
|
|
|
2015-05-08 16:02:36 +00:00
|
|
|
/* create main window */
|
2023-03-16 22:26:44 +00:00
|
|
|
RECT mainWindowPos = registrySettings.WindowPlacement.rcNormalPosition;
|
2016-09-26 19:53:42 +00:00
|
|
|
hwnd = mainWindow.Create(HWND_DESKTOP, mainWindowPos, strTitle, WS_OVERLAPPEDWINDOW);
|
2015-07-07 10:42:49 +00:00
|
|
|
|
2015-08-17 12:03:39 +00:00
|
|
|
RECT fullscreenWindowPos = {0, 0, 100, 100};
|
|
|
|
fullscreenWindow.Create(HWND_DESKTOP, fullscreenWindowPos, NULL, WS_POPUPWINDOW | WS_MAXIMIZE);
|
|
|
|
|
2015-08-16 19:52:37 +00:00
|
|
|
RECT miniaturePos = {(LONG) registrySettings.ThumbXPos, (LONG) registrySettings.ThumbYPos,
|
|
|
|
(LONG) registrySettings.ThumbXPos + (LONG) registrySettings.ThumbWidth,
|
|
|
|
(LONG) registrySettings.ThumbYPos + (LONG) registrySettings.ThumbHeight};
|
2015-07-07 10:42:49 +00:00
|
|
|
miniature.Create(hwnd, miniaturePos, miniaturetitle,
|
2015-07-07 11:44:50 +00:00
|
|
|
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME, WS_EX_PALETTEWINDOW);
|
2015-08-16 19:52:37 +00:00
|
|
|
miniature.ShowWindow(showMiniature ? SW_SHOW : SW_HIDE);
|
2015-05-08 16:02:36 +00:00
|
|
|
|
|
|
|
/* loading and setting the window menu from resource */
|
|
|
|
menu = LoadMenu(hThisInstance, MAKEINTRESOURCE(ID_MENU));
|
|
|
|
SetMenu(hwnd, menu);
|
|
|
|
haccel = LoadAccelerators(hThisInstance, MAKEINTRESOURCE(800));
|
|
|
|
|
2023-03-21 04:13:53 +00:00
|
|
|
/* Create ToolBox */
|
|
|
|
toolBoxContainer.DoCreate(hwnd);
|
2015-05-08 16:02:36 +00:00
|
|
|
|
|
|
|
/* creating the palette child window */
|
2015-07-07 10:42:49 +00:00
|
|
|
RECT paletteWindowPos = {56, 9, 56 + 255, 9 + 32};
|
2023-03-18 08:12:28 +00:00
|
|
|
paletteWindow.Create(hwnd, paletteWindowPos, NULL, WS_CHILD, WS_EX_STATICEDGE);
|
|
|
|
if (registrySettings.ShowPalette)
|
|
|
|
paletteWindow.ShowWindow(SW_SHOWNOACTIVATE);
|
2015-05-08 16:02:36 +00:00
|
|
|
|
2023-03-16 22:45:14 +00:00
|
|
|
// creating the canvas
|
|
|
|
RECT canvasWindowPos = {0, 0, 0 + 500, 0 + 500};
|
|
|
|
canvasWindow.Create(hwnd, canvasWindowPos, NULL,
|
2015-07-07 11:44:50 +00:00
|
|
|
WS_CHILD | WS_GROUP | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE, WS_EX_CLIENTEDGE);
|
2015-05-08 16:02:36 +00:00
|
|
|
|
|
|
|
/* creating the status bar */
|
|
|
|
hStatusBar =
|
2023-03-11 02:41:52 +00:00
|
|
|
CreateWindowEx(0, STATUSCLASSNAME, NULL, SBARS_SIZEGRIP | WS_CHILD, 0, 0, 0, 0, hwnd,
|
2015-05-08 16:02:36 +00:00
|
|
|
NULL, hThisInstance, NULL);
|
|
|
|
SendMessage(hStatusBar, SB_SETMINHEIGHT, 21, 0);
|
2023-03-11 02:41:52 +00:00
|
|
|
if (registrySettings.ShowStatusBar)
|
|
|
|
ShowWindow(hStatusBar, SW_SHOWNOACTIVATE);
|
2015-05-08 16:02:36 +00:00
|
|
|
|
2023-03-16 22:45:14 +00:00
|
|
|
// Creating the window inside the canvas
|
2023-03-16 22:28:42 +00:00
|
|
|
RECT imageAreaPos = {GRIP_SIZE, GRIP_SIZE, GRIP_SIZE + imageModel.GetWidth(), GRIP_SIZE + imageModel.GetHeight()};
|
2023-03-16 22:45:14 +00:00
|
|
|
imageArea.Create(canvasWindow.m_hWnd, imageAreaPos, NULL, WS_CHILD | WS_VISIBLE);
|
2015-05-08 16:02:36 +00:00
|
|
|
|
|
|
|
/* create selection window (initially hidden) */
|
2015-07-07 10:42:49 +00:00
|
|
|
RECT selectionWindowPos = {350, 0, 350 + 100, 0 + 100};
|
2023-03-16 22:28:42 +00:00
|
|
|
selectionWindow.Create(imageArea.m_hWnd, selectionWindowPos, NULL, WS_CHILD | BS_OWNERDRAW);
|
2015-05-08 16:02:36 +00:00
|
|
|
|
2018-05-31 18:17:30 +00:00
|
|
|
if (__argc >= 2)
|
2015-05-08 16:02:36 +00:00
|
|
|
{
|
2020-04-28 22:44:18 +00:00
|
|
|
DoLoadImageFile(mainWindow, __targv[1], TRUE);
|
2015-05-08 16:02:36 +00:00
|
|
|
}
|
|
|
|
|
2022-01-05 07:26:05 +00:00
|
|
|
imageModel.ClearHistory();
|
|
|
|
|
2015-05-08 16:02:36 +00:00
|
|
|
/* initializing the CHOOSECOLOR structure for use with ChooseColor */
|
2019-12-23 19:18:40 +00:00
|
|
|
ZeroMemory(&choosecolor, sizeof(choosecolor));
|
2015-05-08 16:02:36 +00:00
|
|
|
choosecolor.lStructSize = sizeof(CHOOSECOLOR);
|
|
|
|
choosecolor.hwndOwner = hwnd;
|
|
|
|
choosecolor.rgbResult = 0x00ffffff;
|
2019-12-23 19:11:33 +00:00
|
|
|
choosecolor.lpCustColors = custColors;
|
2015-05-08 16:02:36 +00:00
|
|
|
|
|
|
|
/* initializing the OPENFILENAME structure for use with GetOpenFileName and GetSaveFileName */
|
2021-12-25 13:23:25 +00:00
|
|
|
ofnFilename[0] = 0;
|
2016-09-26 19:53:42 +00:00
|
|
|
CString strImporters;
|
|
|
|
CSimpleArray<GUID> aguidFileTypesI;
|
|
|
|
CString strAllPictureFiles;
|
|
|
|
strAllPictureFiles.LoadString(hThisInstance, IDS_ALLPICTUREFILES);
|
|
|
|
CImage::GetImporterFilterString(strImporters, aguidFileTypesI, strAllPictureFiles, CImage::excludeDefaultLoad, _T('\0'));
|
|
|
|
// CAtlStringW strAllFiles;
|
|
|
|
// strAllFiles.LoadString(hThisInstance, IDS_ALLFILES);
|
|
|
|
// strImporters = strAllFiles + CAtlStringW(_T("|*.*|")).Replace('|', '\0') + strImporters;
|
2015-05-08 16:02:36 +00:00
|
|
|
ZeroMemory(&ofn, sizeof(OPENFILENAME));
|
|
|
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
|
|
|
ofn.hwndOwner = hwnd;
|
|
|
|
ofn.hInstance = hThisInstance;
|
2016-09-26 19:53:42 +00:00
|
|
|
ofn.lpstrFilter = strImporters;
|
2015-05-08 16:02:36 +00:00
|
|
|
ofn.lpstrFile = ofnFilename;
|
2021-12-28 01:44:56 +00:00
|
|
|
ofn.nMaxFile = _countof(ofnFilename);
|
2015-05-08 16:02:36 +00:00
|
|
|
ofn.lpstrFileTitle = ofnFiletitle;
|
2021-12-28 01:44:56 +00:00
|
|
|
ofn.nMaxFileTitle = _countof(ofnFiletitle);
|
[NOTEPAD][WORDPAD][MSPAINT]... Use newer file open dialog (#3571)
Use new-style file open/save-as dialog.
- Add OFN_EXPLORER flag to OPENFILENAME structure in notepad, wordpad, mspaint, clipbrd, mmc, mplay32, mscutils, regedit, winhlp32, progman, shellbtrfs, cryptui, shell32, setupapi, vgafontedit, infinst, and vfdlib modules.
2021-04-01 13:50:32 +00:00
|
|
|
ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY;
|
2021-12-25 13:23:25 +00:00
|
|
|
ofn.lpstrDefExt = L"png";
|
2015-05-08 16:02:36 +00:00
|
|
|
|
2016-09-26 19:53:42 +00:00
|
|
|
CopyMemory(sfnFilename, filepathname, sizeof(filepathname));
|
|
|
|
CString strExporters;
|
|
|
|
CSimpleArray<GUID> aguidFileTypesE;
|
|
|
|
CImage::GetExporterFilterString(strExporters, aguidFileTypesE, NULL, CImage::excludeDefaultSave, _T('\0'));
|
2015-05-08 16:02:36 +00:00
|
|
|
ZeroMemory(&sfn, sizeof(OPENFILENAME));
|
|
|
|
sfn.lStructSize = sizeof(OPENFILENAME);
|
|
|
|
sfn.hwndOwner = hwnd;
|
|
|
|
sfn.hInstance = hThisInstance;
|
2016-09-26 19:53:42 +00:00
|
|
|
sfn.lpstrFilter = strExporters;
|
2015-05-08 16:02:36 +00:00
|
|
|
sfn.lpstrFile = sfnFilename;
|
2021-12-28 01:44:56 +00:00
|
|
|
sfn.nMaxFile = _countof(sfnFilename);
|
2015-05-08 16:02:36 +00:00
|
|
|
sfn.lpstrFileTitle = sfnFiletitle;
|
2021-12-28 01:44:56 +00:00
|
|
|
sfn.nMaxFileTitle = _countof(sfnFiletitle);
|
[NOTEPAD][WORDPAD][MSPAINT]... Use newer file open dialog (#3571)
Use new-style file open/save-as dialog.
- Add OFN_EXPLORER flag to OPENFILENAME structure in notepad, wordpad, mspaint, clipbrd, mmc, mplay32, mscutils, regedit, winhlp32, progman, shellbtrfs, cryptui, shell32, setupapi, vgafontedit, infinst, and vfdlib modules.
2021-04-01 13:50:32 +00:00
|
|
|
sfn.Flags = OFN_EXPLORER | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_EXPLORER | OFN_ENABLEHOOK;
|
2017-06-07 10:12:05 +00:00
|
|
|
sfn.lpfnHook = OFNHookProc;
|
2021-12-25 13:23:25 +00:00
|
|
|
sfn.lpstrDefExt = L"png";
|
|
|
|
// Choose PNG
|
|
|
|
for (INT i = 0; i < aguidFileTypesE.GetSize(); ++i)
|
|
|
|
{
|
|
|
|
if (aguidFileTypesE[i] == Gdiplus::ImageFormatPNG)
|
|
|
|
{
|
|
|
|
sfn.nFilterIndex = i + 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-05-08 16:02:36 +00:00
|
|
|
|
|
|
|
/* placing the size boxes around the image */
|
2021-12-26 23:26:33 +00:00
|
|
|
imageArea.SendMessage(WM_SIZE, 0, 0);
|
2015-05-08 16:02:36 +00:00
|
|
|
|
|
|
|
/* Make the window visible on the screen */
|
2023-03-16 22:26:44 +00:00
|
|
|
ShowWindow(hwnd, registrySettings.WindowPlacement.showCmd);
|
2015-05-08 16:02:36 +00:00
|
|
|
|
|
|
|
/* inform the system, that the main window accepts dropped files */
|
|
|
|
DragAcceptFiles(hwnd, TRUE);
|
|
|
|
|
|
|
|
/* Run the message loop. It will run until GetMessage() returns 0 */
|
|
|
|
while (GetMessage(&messages, NULL, 0, 0))
|
|
|
|
{
|
2022-01-05 07:26:05 +00:00
|
|
|
if (fontsDialog.IsWindow() && IsDialogMessage(fontsDialog, &messages))
|
|
|
|
continue;
|
|
|
|
|
2022-02-14 03:08:34 +00:00
|
|
|
if (TranslateAccelerator(hwnd, haccel, &messages))
|
|
|
|
continue;
|
2015-05-08 16:02:36 +00:00
|
|
|
|
|
|
|
/* Translate virtual-key messages into character messages */
|
|
|
|
TranslateMessage(&messages);
|
|
|
|
/* Send message to WindowProcedure */
|
|
|
|
DispatchMessage(&messages);
|
|
|
|
}
|
|
|
|
|
2015-08-16 19:52:37 +00:00
|
|
|
/* write back settings to registry */
|
|
|
|
registrySettings.ShowThumbnail = showMiniature;
|
|
|
|
registrySettings.BMPWidth = imageModel.GetWidth();
|
|
|
|
registrySettings.BMPHeight = imageModel.GetHeight();
|
|
|
|
registrySettings.Store();
|
|
|
|
|
2015-05-08 16:02:36 +00:00
|
|
|
/* The program return-value is 0 - The value that PostQuitMessage() gave */
|
|
|
|
return messages.wParam;
|
|
|
|
}
|