1 /* 2 * PROJECT: PAINT for ReactOS 3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later) 4 * PURPOSE: Initializing everything 5 * COPYRIGHT: Copyright 2015 Benedikt Freisen <b.freisen@gmx.net> 6 */ 7 8 #include "precomp.h" 9 10 POINT g_ptStart, g_ptEnd; 11 BOOL g_askBeforeEnlarging = FALSE; // TODO: initialize from registry 12 HINSTANCE g_hinstExe = NULL; 13 TCHAR g_szFileName[MAX_LONG_PATH] = { 0 }; 14 BOOL g_isAFile = FALSE; 15 BOOL g_imageSaved = FALSE; 16 BOOL g_showGrid = FALSE; 17 18 CMainWindow mainWindow; 19 20 /* FUNCTIONS ********************************************************/ 21 22 // get file name extension from filter string 23 static BOOL 24 FileExtFromFilter(LPTSTR pExt, OPENFILENAME *pOFN) 25 { 26 LPTSTR pchExt = pExt; 27 *pchExt = 0; 28 29 DWORD nIndex = 1; 30 for (LPCTSTR pch = pOFN->lpstrFilter; *pch; ++nIndex) 31 { 32 pch += lstrlen(pch) + 1; 33 if (pOFN->nFilterIndex == nIndex) 34 { 35 for (++pch; *pch && *pch != _T(';'); ++pch) 36 { 37 *pchExt++ = *pch; 38 } 39 *pchExt = 0; 40 CharLower(pExt); 41 return TRUE; 42 } 43 pch += lstrlen(pch) + 1; 44 } 45 return FALSE; 46 } 47 48 // Hook procedure for OPENFILENAME to change the file name extension 49 static UINT_PTR APIENTRY 50 OFNHookProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 51 { 52 HWND hParent; 53 OFNOTIFY *pon; 54 switch (uMsg) 55 { 56 case WM_NOTIFY: 57 pon = (OFNOTIFY *)lParam; 58 if (pon->hdr.code == CDN_TYPECHANGE) 59 { 60 hParent = GetParent(hwnd); 61 TCHAR Path[MAX_PATH]; 62 SendMessage(hParent, CDM_GETFILEPATH, _countof(Path), (LPARAM)Path); 63 FileExtFromFilter(PathFindExtension(Path), pon->lpOFN); 64 SendMessage(hParent, CDM_SETCONTROLTEXT, 0x047c, (LPARAM)PathFindFileName(Path)); 65 lstrcpyn(pon->lpOFN->lpstrFile, Path, pon->lpOFN->nMaxFile); 66 } 67 break; 68 } 69 return 0; 70 } 71 72 BOOL CMainWindow::GetOpenFileName(IN OUT LPTSTR pszFile, INT cchMaxFile) 73 { 74 static OPENFILENAME ofn = { 0 }; 75 static CString strFilter; 76 77 if (ofn.lStructSize == 0) 78 { 79 // The "All Files" item text 80 CString strAllPictureFiles; 81 strAllPictureFiles.LoadString(g_hinstExe, IDS_ALLPICTUREFILES); 82 83 // Get the import filter 84 CSimpleArray<GUID> aguidFileTypesI; 85 CImage::GetImporterFilterString(strFilter, aguidFileTypesI, strAllPictureFiles, 86 CImage::excludeDefaultLoad, _T('\0')); 87 88 // Initializing the OPENFILENAME structure for GetOpenFileName 89 ZeroMemory(&ofn, sizeof(ofn)); 90 ofn.lStructSize = sizeof(ofn); 91 ofn.hwndOwner = m_hWnd; 92 ofn.hInstance = g_hinstExe; 93 ofn.lpstrFilter = strFilter; 94 ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY; 95 ofn.lpstrDefExt = L"png"; 96 } 97 98 ofn.lpstrFile = pszFile; 99 ofn.nMaxFile = cchMaxFile; 100 return ::GetOpenFileName(&ofn); 101 } 102 103 BOOL CMainWindow::GetSaveFileName(IN OUT LPTSTR pszFile, INT cchMaxFile) 104 { 105 static OPENFILENAME sfn = { 0 }; 106 static CString strFilter; 107 108 if (sfn.lStructSize == 0) 109 { 110 // Get the export filter 111 CSimpleArray<GUID> aguidFileTypesE; 112 CImage::GetExporterFilterString(strFilter, aguidFileTypesE, NULL, 113 CImage::excludeDefaultSave, _T('\0')); 114 115 // Initializing the OPENFILENAME structure for GetSaveFileName 116 ZeroMemory(&sfn, sizeof(sfn)); 117 sfn.lStructSize = sizeof(sfn); 118 sfn.hwndOwner = m_hWnd; 119 sfn.hInstance = g_hinstExe; 120 sfn.lpstrFilter = strFilter; 121 sfn.Flags = OFN_EXPLORER | OFN_OVERWRITEPROMPT | OFN_ENABLEHOOK; 122 sfn.lpfnHook = OFNHookProc; 123 sfn.lpstrDefExt = L"png"; 124 125 LPWSTR pchDotExt = PathFindExtensionW(pszFile); 126 if (*pchDotExt == UNICODE_NULL) 127 { 128 // Choose PNG 129 wcscat(pszFile, L".png"); 130 for (INT i = 0; i < aguidFileTypesE.GetSize(); ++i) 131 { 132 if (aguidFileTypesE[i] == Gdiplus::ImageFormatPNG) 133 { 134 sfn.nFilterIndex = i + 1; 135 break; 136 } 137 } 138 } 139 } 140 141 sfn.lpstrFile = pszFile; 142 sfn.nMaxFile = cchMaxFile; 143 return ::GetSaveFileName(&sfn); 144 } 145 146 BOOL CMainWindow::ChooseColor(IN OUT COLORREF *prgbColor) 147 { 148 static CHOOSECOLOR choosecolor = { 0 }; 149 static COLORREF custColors[16] = 150 { 151 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 152 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff 153 }; 154 155 if (choosecolor.lStructSize == 0) 156 { 157 // Initializing the CHOOSECOLOR structure for ChooseColor 158 ZeroMemory(&choosecolor, sizeof(choosecolor)); 159 choosecolor.lStructSize = sizeof(choosecolor); 160 choosecolor.hwndOwner = m_hWnd; 161 choosecolor.lpCustColors = custColors; 162 } 163 164 choosecolor.Flags = CC_RGBINIT; 165 choosecolor.rgbResult = *prgbColor; 166 if (!::ChooseColor(&choosecolor)) 167 return FALSE; 168 169 *prgbColor = choosecolor.rgbResult; 170 return TRUE; 171 } 172 173 HWND CMainWindow::DoCreate() 174 { 175 ::LoadString(g_hinstExe, IDS_DEFAULTFILENAME, g_szFileName, _countof(g_szFileName)); 176 177 CString strTitle; 178 strTitle.Format(IDS_WINDOWTITLE, PathFindFileName(g_szFileName)); 179 180 RECT& rc = registrySettings.WindowPlacement.rcNormalPosition; 181 return Create(HWND_DESKTOP, rc, strTitle, WS_OVERLAPPEDWINDOW, WS_EX_ACCEPTFILES); 182 } 183 184 // entry point 185 INT WINAPI 186 _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, INT nCmdShow) 187 { 188 #ifdef _DEBUG 189 // Report any memory leaks on exit 190 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 191 #endif 192 193 g_hinstExe = hInstance; 194 195 // Initialize common controls library 196 INITCOMMONCONTROLSEX iccx; 197 iccx.dwSize = sizeof(iccx); 198 iccx.dwICC = ICC_STANDARD_CLASSES | ICC_USEREX_CLASSES | ICC_BAR_CLASSES; 199 InitCommonControlsEx(&iccx); 200 201 // Load settings from registry 202 registrySettings.Load(nCmdShow); 203 204 // Create the main window 205 if (!mainWindow.DoCreate()) 206 { 207 MessageBox(NULL, TEXT("Failed to create main window."), NULL, MB_ICONERROR); 208 return 1; 209 } 210 211 // Initialize imageModel 212 imageModel.Crop(registrySettings.BMPWidth, registrySettings.BMPHeight); 213 if (__argc >= 2) 214 DoLoadImageFile(mainWindow, __targv[1], TRUE); 215 imageModel.ClearHistory(); 216 217 // Make the window visible on the screen 218 mainWindow.ShowWindow(registrySettings.WindowPlacement.showCmd); 219 220 // Load the access keys 221 HACCEL hAccel = ::LoadAccelerators(hInstance, MAKEINTRESOURCE(800)); 222 223 // The message loop 224 MSG msg; 225 while (::GetMessage(&msg, NULL, 0, 0)) 226 { 227 if (fontsDialog.IsWindow() && fontsDialog.IsDialogMessage(&msg)) 228 continue; 229 230 if (::TranslateAccelerator(mainWindow, hAccel, &msg)) 231 continue; 232 233 ::TranslateMessage(&msg); 234 ::DispatchMessage(&msg); 235 } 236 237 // Unload the access keys 238 ::DestroyAcceleratorTable(hAccel); 239 240 // Write back settings to registry 241 registrySettings.Store(); 242 243 // Return the value that PostQuitMessage() gave 244 return (INT)msg.wParam; 245 } 246