mirror of
https://github.com/reactos/reactos.git
synced 2024-09-06 19:02:32 +00:00
369 lines
11 KiB
C++
369 lines
11 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"
|
|
|
|
#include <dlgs.h>
|
|
#include <mapi.h>
|
|
|
|
BOOL g_askBeforeEnlarging = FALSE; // TODO: initialize from registry
|
|
HINSTANCE g_hinstExe = NULL;
|
|
WCHAR g_szFileName[MAX_LONG_PATH] = { 0 };
|
|
WCHAR g_szMailTempFile[MAX_LONG_PATH] = { 0 };
|
|
BOOL g_isAFile = FALSE;
|
|
BOOL g_imageSaved = FALSE;
|
|
BOOL g_showGrid = FALSE;
|
|
|
|
CMainWindow mainWindow;
|
|
|
|
/* FUNCTIONS ********************************************************/
|
|
|
|
void ShowOutOfMemory(void)
|
|
{
|
|
WCHAR szText[256];
|
|
::FormatMessageW(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
|
|
NULL,
|
|
ERROR_OUTOFMEMORY,
|
|
0,
|
|
szText, _countof(szText),
|
|
NULL);
|
|
mainWindow.MessageBox(szText, NULL, MB_ICONERROR);
|
|
}
|
|
|
|
// get file name extension from filter string
|
|
static BOOL
|
|
FileExtFromFilter(LPWSTR pExt, OPENFILENAME *pOFN)
|
|
{
|
|
LPWSTR pchExt = pExt;
|
|
*pchExt = 0;
|
|
|
|
DWORD nIndex = 1;
|
|
for (LPCWSTR pch = pOFN->lpstrFilter; *pch; ++nIndex)
|
|
{
|
|
pch += lstrlen(pch) + 1;
|
|
if (pOFN->nFilterIndex == nIndex)
|
|
{
|
|
for (++pch; *pch && *pch != L';'; ++pch)
|
|
{
|
|
*pchExt++ = *pch;
|
|
}
|
|
*pchExt = 0;
|
|
CharLower(pExt);
|
|
return TRUE;
|
|
}
|
|
pch += wcslen(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;
|
|
OFNOTIFYW *pon;
|
|
WCHAR Path[MAX_PATH];
|
|
switch (uMsg)
|
|
{
|
|
case WM_NOTIFY:
|
|
pon = (OFNOTIFYW *)lParam;
|
|
if (pon->hdr.code == CDN_TYPECHANGE)
|
|
{
|
|
hParent = GetParent(hwnd);
|
|
SendMessageW(hParent, CDM_GETFILEPATH, _countof(Path), (LPARAM)Path);
|
|
FileExtFromFilter(PathFindExtensionW(Path), pon->lpOFN);
|
|
SendMessageW(hParent, CDM_SETCONTROLTEXT, cmb13, (LPARAM)PathFindFileNameW(Path));
|
|
StringCchCopyW(pon->lpOFN->lpstrFile, pon->lpOFN->nMaxFile, Path);
|
|
}
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
typedef ULONG (WINAPI *FN_MAPISendMail)(LHANDLE, ULONG_PTR, lpMapiMessage, FLAGS, ULONG);
|
|
typedef ULONG (WINAPI *FN_MAPISendMailW)(LHANDLE, ULONG_PTR, lpMapiMessageW, FLAGS, ULONG);
|
|
|
|
BOOL OpenMailer(HWND hWnd, LPCWSTR pszPathName)
|
|
{
|
|
// Delete the temporary file if any
|
|
if (g_szMailTempFile[0])
|
|
{
|
|
::DeleteFileW(g_szMailTempFile);
|
|
g_szMailTempFile[0] = UNICODE_NULL;
|
|
}
|
|
|
|
CStringW strFileTitle;
|
|
if (PathFileExistsW(pszPathName) && imageModel.IsImageSaved())
|
|
{
|
|
strFileTitle = PathFindFileNameW(pszPathName);
|
|
}
|
|
else // Not existing or not saved
|
|
{
|
|
// Get the name of a temporary file
|
|
WCHAR szTempDir[MAX_PATH];
|
|
::GetTempPathW(_countof(szTempDir), szTempDir);
|
|
if (!::GetTempFileNameW(szTempDir, L"afx", 0, g_szMailTempFile))
|
|
return FALSE; // Failure
|
|
|
|
if (PathFileExistsW(g_szFileName))
|
|
{
|
|
// Set file title
|
|
strFileTitle = PathFindFileNameW(g_szFileName);
|
|
|
|
// Copy to the temporary file
|
|
if (!::CopyFileW(g_szFileName, g_szMailTempFile, FALSE))
|
|
{
|
|
g_szMailTempFile[0] = UNICODE_NULL;
|
|
return FALSE; // Failure
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Set file title
|
|
strFileTitle.LoadString(IDS_DEFAULTFILENAME);
|
|
strFileTitle += L".png";
|
|
|
|
// Save it to the temporary file
|
|
HBITMAP hbmLocked = imageModel.LockBitmap();
|
|
BOOL ret = SaveDIBToFile(hbmLocked, g_szMailTempFile, FALSE, Gdiplus::ImageFormatPNG);
|
|
imageModel.UnlockBitmap(hbmLocked);
|
|
if (!ret)
|
|
{
|
|
g_szMailTempFile[0] = UNICODE_NULL;
|
|
return FALSE; // Failure
|
|
}
|
|
}
|
|
|
|
// Use the temporary file
|
|
pszPathName = g_szMailTempFile;
|
|
}
|
|
|
|
// Load "mapi32.dll"
|
|
HINSTANCE hMAPI = LoadLibraryW(L"mapi32.dll");
|
|
if (!hMAPI)
|
|
return FALSE; // Failure
|
|
|
|
// Attachment
|
|
MapiFileDescW attachmentW = { 0 };
|
|
attachmentW.nPosition = (ULONG)-1;
|
|
attachmentW.lpszPathName = (LPWSTR)pszPathName;
|
|
attachmentW.lpszFileName = (LPWSTR)(LPCWSTR)strFileTitle;
|
|
|
|
// Message with attachment
|
|
MapiMessageW messageW = { 0 };
|
|
messageW.lpszSubject = NULL;
|
|
messageW.nFileCount = 1;
|
|
messageW.lpFiles = &attachmentW;
|
|
|
|
// First, try to open the mailer by the function of Unicode version
|
|
FN_MAPISendMailW pMAPISendMailW = (FN_MAPISendMailW)::GetProcAddress(hMAPI, "MAPISendMailW");
|
|
if (pMAPISendMailW)
|
|
{
|
|
pMAPISendMailW(0, (ULONG_PTR)hWnd, &messageW, MAPI_DIALOG | MAPI_LOGON_UI, 0);
|
|
::FreeLibrary(hMAPI);
|
|
return TRUE; // MAPISendMailW will show an error message on failure
|
|
}
|
|
|
|
// Convert to ANSI strings
|
|
CStringA szPathNameA(pszPathName), szFileTitleA(strFileTitle);
|
|
|
|
MapiFileDesc attachment = { 0 };
|
|
attachment.nPosition = (ULONG)-1;
|
|
attachment.lpszPathName = (LPSTR)(LPCSTR)szPathNameA;
|
|
attachment.lpszFileName = (LPSTR)(LPCSTR)szFileTitleA;
|
|
|
|
MapiMessage message = { 0 };
|
|
message.lpszSubject = NULL;
|
|
message.nFileCount = 1;
|
|
message.lpFiles = &attachment;
|
|
|
|
// Try again but in ANSI version
|
|
FN_MAPISendMail pMAPISendMail = (FN_MAPISendMail)::GetProcAddress(hMAPI, "MAPISendMail");
|
|
if (pMAPISendMail)
|
|
{
|
|
pMAPISendMail(0, (ULONG_PTR)hWnd, &message, MAPI_DIALOG | MAPI_LOGON_UI, 0);
|
|
::FreeLibrary(hMAPI);
|
|
return TRUE; // MAPISendMail will show an error message on failure
|
|
}
|
|
|
|
::FreeLibrary(hMAPI);
|
|
return FALSE; // Failure
|
|
}
|
|
|
|
BOOL CMainWindow::GetOpenFileName(IN OUT LPWSTR pszFile, INT cchMaxFile)
|
|
{
|
|
static OPENFILENAMEW ofn = { 0 };
|
|
static CStringW strFilter;
|
|
|
|
if (ofn.lStructSize == 0)
|
|
{
|
|
// The "All Files" item text
|
|
CStringW strAllPictureFiles;
|
|
strAllPictureFiles.LoadString(g_hinstExe, IDS_ALLPICTUREFILES);
|
|
|
|
// Get the import filter
|
|
CSimpleArray<GUID> aguidFileTypesI;
|
|
CImage::GetImporterFilterString(strFilter, aguidFileTypesI, strAllPictureFiles,
|
|
CImage::excludeDefaultLoad, L'|');
|
|
strFilter.Replace(L'|', UNICODE_NULL);
|
|
|
|
// 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 ::GetOpenFileNameW(&ofn);
|
|
}
|
|
|
|
BOOL CMainWindow::GetSaveFileName(IN OUT LPWSTR pszFile, INT cchMaxFile)
|
|
{
|
|
static OPENFILENAMEW sfn = { 0 };
|
|
static CStringW strFilter;
|
|
|
|
if (sfn.lStructSize == 0)
|
|
{
|
|
// Get the export filter
|
|
CSimpleArray<GUID> aguidFileTypesE;
|
|
CImage::GetExporterFilterString(strFilter, aguidFileTypesE, NULL,
|
|
CImage::excludeDefaultSave, L'|');
|
|
strFilter.Replace(L'|', UNICODE_NULL);
|
|
|
|
// 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
|
|
StringCchCatW(pszFile, cchMaxFile, 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 ::GetSaveFileNameW(&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()
|
|
{
|
|
::LoadStringW(g_hinstExe, IDS_DEFAULTFILENAME, g_szFileName, _countof(g_szFileName));
|
|
|
|
CStringW 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
|
|
wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, INT nCmdShow)
|
|
{
|
|
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, L"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 = ::LoadAcceleratorsW(hInstance, MAKEINTRESOURCEW(800));
|
|
|
|
// The message loop
|
|
MSG msg;
|
|
while (::GetMessage(&msg, NULL, 0, 0))
|
|
{
|
|
if (fontsDialog.IsWindow() && fontsDialog.IsDialogMessage(&msg))
|
|
continue;
|
|
|
|
if (::TranslateAcceleratorW(mainWindow, hAccel, &msg))
|
|
continue;
|
|
|
|
::TranslateMessage(&msg);
|
|
::DispatchMessage(&msg);
|
|
}
|
|
|
|
// Unload the access keys
|
|
::DestroyAcceleratorTable(hAccel);
|
|
|
|
// Write back settings to registry
|
|
registrySettings.Store();
|
|
|
|
if (g_szMailTempFile[0])
|
|
::DeleteFileW(g_szMailTempFile);
|
|
|
|
// Return the value that PostQuitMessage() gave
|
|
return (INT)msg.wParam;
|
|
}
|