// FM.cpp #include "StdAfx.h" #include "resource.h" #include "Panel.h" extern "C" { #include "../../../C/Alloc.h" } #include "Common/Defs.h" #include "Common/StringConvert.h" // #include "Common/CommandLineParser.h" #include "Windows/Control/Toolbar.h" #include "Windows/Error.h" #include "Windows/COM.h" #include "Windows/DLL.h" #include "Windows/Security.h" #include "Windows/MemoryLock.h" #include "ViewSettings.h" #include "../UI/Resource/Extract/resource.h" #include "App.h" #include "StringUtils.h" #include "MyLoadMenu.h" #include "LangUtils.h" #include "FormatUtils.h" #include "RegistryUtils.h" using namespace NWindows; using namespace NFile; using namespace NFind; // using namespace NCommandLineParser; #define MAX_LOADSTRING 100 #define MENU_HEIGHT 26 #ifndef _UNICODE bool g_IsNT = false; #endif HINSTANCE g_hInstance; HWND g_HWND; bool g_OpenArchive = false; static UString g_MainPath; const int kNumDefaultPanels = 1; const int kSplitterWidth = 4; int kSplitterRateMax = 1 << 16; // bool OnMenuCommand(HWND hWnd, int id); static UString GetProgramPath() { UString s; NDLL::MyGetModuleFileName(g_hInstance, s); return s; } UString GetProgramFolderPrefix() { UString path = GetProgramPath(); int pos = path.ReverseFind(L'\\'); return path.Left(pos + 1); } class CSplitterPos { int _ratio; // 10000 is max int _pos; int _fullWidth; void SetRatioFromPos(HWND hWnd) { _ratio = (_pos + kSplitterWidth / 2) * kSplitterRateMax / MyMax(GetWidth(hWnd), 1); } public: int GetPos() const { return _pos; } int GetWidth(HWND hWnd) const { RECT rect; ::GetClientRect(hWnd, &rect); return rect.right; } void SetRatio(HWND hWnd, int aRatio) { _ratio = aRatio; SetPosFromRatio(hWnd); } void SetPosPure(HWND hWnd, int pos) { int posMax = GetWidth(hWnd) - kSplitterWidth; if (pos > posMax) pos = posMax; if (pos < 0) pos = 0; _pos = pos; } void SetPos(HWND hWnd, int pos) { _fullWidth = GetWidth(hWnd); SetPosPure(hWnd, pos); SetRatioFromPos(hWnd); } void SetPosFromRatio(HWND hWnd) { int fullWidth = GetWidth(hWnd); if (_fullWidth != fullWidth) { _fullWidth = fullWidth; SetPosPure(hWnd, GetWidth(hWnd) * _ratio / kSplitterRateMax - kSplitterWidth / 2); } } }; bool g_CanChangeSplitter = false; UINT32 g_SplitterPos = 0; CSplitterPos g_Splitter; bool g_PanelsInfoDefined = false; int g_StartCaptureMousePos; int g_StartCaptureSplitterPos; CApp g_App; void MoveSubWindows(HWND hWnd); void OnSize(HWND hWnd); LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); const wchar_t *kWindowClass = L"FM"; #ifndef _UNICODE static bool IsItWindowsNT() { OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); } #endif // FUNCTION: InitInstance(HANDLE, int) BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { CWindow wnd; g_hInstance = hInstance; ReloadLangSmart(); // LoadString(hInstance, IDS_CLASS, windowClass, MAX_LOADSTRING); // LoadString(hInstance, IDS_APP_TITLE, title, MAX_LOADSTRING); UString title = LangString(IDS_APP_TITLE, 0x03000000); /* //If it is already running, then focus on the window hWnd = FindWindow(windowClass, title); if (hWnd) { SetForegroundWindow ((HWND) (((DWORD)hWnd) | 0x01)); return 0; } */ WNDCLASSW wc; // wc.style = CS_HREDRAW | CS_VREDRAW; wc.style = 0; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_FAM)); // wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.hCursor = ::LoadCursor(0, IDC_SIZEWE); // wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1); wc.lpszMenuName = MAKEINTRESOURCEW(IDM_MENU); wc.lpszClassName = kWindowClass; MyRegisterClass(&wc); // RECT rect; // GetClientRect(hWnd, &rect); DWORD style = WS_OVERLAPPEDWINDOW; // DWORD style = 0; RECT rect; bool maximized = false; int x , y, xSize, ySize; x = y = xSize = ySize = CW_USEDEFAULT; bool windowPosIsRead = ReadWindowSize(rect, maximized); if (windowPosIsRead) { // x = rect.left; // y = rect.top; xSize = rect.right - rect.left; ySize = rect.bottom - rect.top; } UINT32 numPanels, currentPanel; g_PanelsInfoDefined = ReadPanelsInfo(numPanels, currentPanel, g_SplitterPos); if (g_PanelsInfoDefined) { if (numPanels < 1 || numPanels > 2) numPanels = kNumDefaultPanels; if (currentPanel >= 2) currentPanel = 0; } else { numPanels = kNumDefaultPanels; currentPanel = 0; } g_App.NumPanels = numPanels; g_App.LastFocusedPanel = currentPanel; if (!wnd.Create(kWindowClass, title, style, x, y, xSize, ySize, NULL, NULL, hInstance, NULL)) return FALSE; g_HWND = (HWND)wnd; WINDOWPLACEMENT placement; placement.length = sizeof(placement); if (wnd.GetPlacement(&placement)) { if (nCmdShow == SW_SHOWNORMAL || nCmdShow == SW_SHOW || nCmdShow == SW_SHOWDEFAULT) { if (maximized) placement.showCmd = SW_SHOWMAXIMIZED; else placement.showCmd = SW_SHOWNORMAL; } else placement.showCmd = nCmdShow; if (windowPosIsRead) placement.rcNormalPosition = rect; wnd.SetPlacement(&placement); // window.Show(nCmdShow); } else wnd.Show(nCmdShow); return TRUE; } /* static void GetCommands(const UString &aCommandLine, UString &aCommands) { UString aProgramName; aCommands.Empty(); bool aQuoteMode = false; for (int i = 0; i < aCommandLine.Length(); i++) { wchar_t aChar = aCommandLine[i]; if (aChar == L'\"') aQuoteMode = !aQuoteMode; else if (aChar == L' ' && !aQuoteMode) { if (!aQuoteMode) { i++; break; } } else aProgramName += aChar; } aCommands = aCommandLine.Mid(i); } */ DWORD GetDllVersion(LPCTSTR lpszDllName) { HINSTANCE hinstDll; DWORD dwVersion = 0; hinstDll = LoadLibrary(lpszDllName); if(hinstDll) { DLLGETVERSIONPROC pDllGetVersion; pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hinstDll, "DllGetVersion"); /*Because some DLLs might not implement this function, you must test for it explicitly. Depending on the particular DLL, the lack of a DllGetVersion function can be a useful indicator of the version. */ if(pDllGetVersion) { DLLVERSIONINFO dvi; HRESULT hr; ZeroMemory(&dvi, sizeof(dvi)); dvi.cbSize = sizeof(dvi); hr = (*pDllGetVersion)(&dvi); if(SUCCEEDED(hr)) { dwVersion = MAKELONG(dvi.dwMinorVersion, dvi.dwMajorVersion); } } FreeLibrary(hinstDll); } return dwVersion; } DWORD g_ComCtl32Version; /* #ifndef _WIN64 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); static bool IsWow64() { LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress( GetModuleHandle("kernel32"), "IsWow64Process"); if (fnIsWow64Process == NULL) return false; BOOL isWow; if (!fnIsWow64Process(GetCurrentProcess(),&isWow)) return false; return isWow != FALSE; } #endif */ bool IsLargePageSupported() { #ifdef _WIN64 return true; #else OSVERSIONINFO versionInfo; versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); if (!::GetVersionEx(&versionInfo)) return false; if (versionInfo.dwPlatformId != VER_PLATFORM_WIN32_NT || versionInfo.dwMajorVersion < 5) return false; if (versionInfo.dwMajorVersion > 5) return true; if (versionInfo.dwMinorVersion < 1) return false; if (versionInfo.dwMinorVersion > 1) return true; // return IsWow64(); return false; #endif } static void SetMemoryLock() { if (!IsLargePageSupported()) return; // if (ReadLockMemoryAdd()) NSecurity::AddLockMemoryPrivilege(); if (ReadLockMemoryEnable()) NSecurity::EnableLockMemoryPrivilege(); } /* static const int kNumSwitches = 1; namespace NKey { enum Enum { kOpenArachive = 0, }; } static const CSwitchForm kSwitchForms[kNumSwitches] = { { L"SOA", NSwitchType::kSimple, false }, }; */ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */, LPSTR /* lpCmdLine */, int nCmdShow) { #ifndef _UNICODE g_IsNT = IsItWindowsNT(); #endif #ifdef _WIN32 SetLargePageSize(); #endif InitCommonControls(); g_ComCtl32Version = ::GetDllVersion(TEXT("comctl32.dll")); // OleInitialize is required for drag and drop. OleInitialize(NULL); // Maybe needs CoInitializeEx also ? // NCOM::CComInitializer comInitializer; UString programString, commandsString; // MessageBoxW(0, GetCommandLineW(), L"", 0); SplitStringToTwoStrings(GetCommandLineW(), programString, commandsString); commandsString.Trim(); UString paramString, tailString; SplitStringToTwoStrings(commandsString, paramString, tailString); paramString.Trim(); if (!paramString.IsEmpty()) { g_MainPath = paramString; // MessageBoxW(0, paramString, L"", 0); } /* UStringVector commandStrings; NCommandLineParser::SplitCommandLine(GetCommandLineW(), commandStrings); NCommandLineParser::CParser parser(kNumSwitches); try { parser.ParseStrings(kSwitchForms, commandStrings); const UStringVector &nonSwitchStrings = parser.NonSwitchStrings; if(nonSwitchStrings.Size() > 1) { g_MainPath = nonSwitchStrings[1]; // g_OpenArchive = parser[NKey::kOpenArachive].ThereIs; CFileInfoW fileInfo; if (FindFile(g_MainPath, fileInfo)) { if (!fileInfo.IsDirectory()) g_OpenArchive = true; } } } catch(...) { } */ SetMemoryLock(); MSG msg; if (!InitInstance (hInstance, nCmdShow)) return FALSE; MyLoadMenu(g_HWND); #ifndef _UNICODE if (g_IsNT) { HACCEL hAccels = LoadAcceleratorsW(hInstance, MAKEINTRESOURCEW(IDR_ACCELERATOR1)); while (GetMessageW(&msg, NULL, 0, 0)) { if (TranslateAcceleratorW(g_HWND, hAccels, &msg) == 0) { TranslateMessage(&msg); DispatchMessageW(&msg); } } } else #endif { HACCEL hAccels = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1)); while (GetMessage(&msg, NULL, 0, 0)) { if (TranslateAccelerator(g_HWND, hAccels, &msg) == 0) { // if (g_Hwnd != NULL || !IsDialogMessage(g_Hwnd, &msg)) // if (!IsDialogMessage(g_Hwnd, &msg)) TranslateMessage(&msg); DispatchMessage(&msg); } } } g_HWND = 0; OleUninitialize(); return (int)msg.wParam; } static void SaveWindowInfo(HWND aWnd) { /* RECT rect; if (!::GetWindowRect(aWnd, &rect)) return; */ WINDOWPLACEMENT placement; placement.length = sizeof(placement); if (!::GetWindowPlacement(aWnd, &placement)) return; SaveWindowSize(placement.rcNormalPosition, BOOLToBool(::IsZoomed(aWnd))); SavePanelsInfo(g_App.NumPanels, g_App.LastFocusedPanel, g_Splitter.GetPos()); } void ExecuteCommand(UINT commandID) { switch (commandID) { case kAddCommand: g_App.AddToArchive(); break; case kExtractCommand: g_App.ExtractArchives(); break; case kTestCommand: g_App.TestArchives(); break; } } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); if ((HWND) lParam != NULL && wmEvent != 0) break; if (wmId >= kToolbarStartID) { ExecuteCommand(wmId); return 0; } if (OnMenuCommand(hWnd, wmId)) return 0; break; case WM_INITMENUPOPUP: OnMenuActivating(hWnd, HMENU(wParam), LOWORD(lParam)); break; /* It doesn't help case WM_EXITMENULOOP: { OnMenuUnActivating(hWnd); break; } case WM_UNINITMENUPOPUP: OnMenuUnActivating(hWnd, HMENU(wParam), lParam); break; */ case WM_CREATE: { /* INITCOMMONCONTROLSEX icex; icex.dwSize = sizeof(INITCOMMONCONTROLSEX); icex.dwICC = ICC_BAR_CLASSES; InitCommonControlsEx(&icex); // Toolbar buttons used to create the first 4 buttons. TBBUTTON tbb [ ] = { // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0}, // {VIEW_PARENTFOLDER, kParentFolderID, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0}, // {0, 0, TBSTATE_ENABLED, BTNS_SEP, 0L, 0}, {VIEW_NEWFOLDER, ID_FILE_CREATEFOLDER, TBSTATE_ENABLED, BTNS_BUTTON, 0L, 0}, }; int baseID = 100; NWindows::NControl::CToolBar aToolBar; aToolBar.Attach(::CreateToolbarEx (hWnd, WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS, // | TBSTYLE_FLAT baseID + 2, 11, (HINSTANCE)HINST_COMMCTRL, IDB_VIEW_SMALL_COLOR, (LPCTBBUTTON)&tbb, sizeof(tbb) / sizeof(tbb[0]), 0, 0, 100, 30, sizeof (TBBUTTON))); */ // HCURSOR cursor = ::LoadCursor(0, IDC_SIZEWE); // ::SetCursor(cursor); if (g_PanelsInfoDefined) g_Splitter.SetPos(hWnd, g_SplitterPos); else { g_Splitter.SetRatio(hWnd, kSplitterRateMax / 2); g_SplitterPos = g_Splitter.GetPos(); } RECT rect; ::GetClientRect(hWnd, &rect); int xSize = rect.right; int xSizes[2]; xSizes[0] = g_Splitter.GetPos(); xSizes[1] = xSize - kSplitterWidth - xSizes[0]; if (xSizes[1] < 0) xSizes[1] = 0; g_App.CreateDragTarget(); bool archiveIsOpened; bool encrypted; bool needOpenFile = false; if (!g_MainPath.IsEmpty() /* && g_OpenArchive */) { NFile::NFind::CFileInfoW fileInfo; if (NFile::NFind::FindFile(g_MainPath, fileInfo)) if (!fileInfo.IsDirectory()) needOpenFile = true; } g_App.Create(hWnd, g_MainPath, xSizes, archiveIsOpened, encrypted); if (needOpenFile && !archiveIsOpened) { UString message; if (encrypted) message = MyFormatNew(IDS_CANT_OPEN_ENCRYPTED_ARCHIVE, 0x0200060A, g_MainPath); else message = MyFormatNew(IDS_CANT_OPEN_ARCHIVE, 0x02000609, g_MainPath); MessageBoxW(0, message, L"7-zip", MB_ICONERROR); return -1; } // g_SplitterPos = 0; // ::DragAcceptFiles(hWnd, TRUE); RegisterDragDrop(hWnd, g_App._dropTarget); break; } case WM_DESTROY: { // ::DragAcceptFiles(hWnd, FALSE); RevokeDragDrop(hWnd); g_App._dropTarget.Release(); g_App.Save(); g_App.Release(); SaveWindowInfo(hWnd); PostQuitMessage(0); break; } /* case WM_MOVE: { break; } */ case WM_LBUTTONDOWN: g_StartCaptureMousePos = LOWORD(lParam); g_StartCaptureSplitterPos = g_Splitter.GetPos(); ::SetCapture(hWnd); break; case WM_LBUTTONUP: { ::ReleaseCapture(); break; } case WM_MOUSEMOVE: { if ((wParam & MK_LBUTTON) != 0 && ::GetCapture() == hWnd) { g_Splitter.SetPos(hWnd, g_StartCaptureSplitterPos + (short)LOWORD(lParam) - g_StartCaptureMousePos); MoveSubWindows(hWnd); } break; } case WM_SIZE: { if (g_CanChangeSplitter) g_Splitter.SetPosFromRatio(hWnd); else { g_Splitter.SetPos(hWnd, g_SplitterPos ); g_CanChangeSplitter = true; } OnSize(hWnd); /* int xSize = LOWORD(lParam); int ySize = HIWORD(lParam); // int xSplitter = 2; int xWidth = g_SplitPos; // int xSplitPos = xWidth; g_Panel[0]._listView.MoveWindow(0, 0, xWidth, ySize); g_Panel[1]._listView.MoveWindow(xSize - xWidth, 0, xWidth, ySize); */ return 0; break; } case WM_SETFOCUS: // g_App.SetFocus(g_App.LastFocusedPanel); g_App.SetFocusToLastItem(); break; /* case WM_ACTIVATE: { int fActive = LOWORD(wParam); switch (fActive) { case WA_INACTIVE: { // g_FocusIndex = g_App.LastFocusedPanel; // g_App.LastFocusedPanel = g_App.GetFocusedPanelIndex(); // return 0; } } break; } */ /* case kLangWasChangedMessage: MyLoadMenu(g_HWND); return 0; */ /* case WM_SETTINGCHANGE: break; */ case WM_NOTIFY: { g_App.OnNotify((int)wParam, (LPNMHDR)lParam); break; } /* case WM_DROPFILES: { g_App.GetFocusedPanel().CompressDropFiles((HDROP)wParam); return 0 ; } */ } #ifndef _UNICODE if (g_IsNT) return DefWindowProcW(hWnd, message, wParam, lParam); else #endif return DefWindowProc(hWnd, message, wParam, lParam); } void OnSize(HWND hWnd) { /* if (g_App._rebar) { RECT rect; ::GetClientRect(hWnd, &rect); int xSize = rect.right; int ySize = rect.bottom; // rect.bottom = 0; // g_App._rebar.SizeToRect(&rect); // g_App._rebar.Move(0, 0, xSize, ySize); } */ MoveSubWindows(hWnd); } void MoveSubWindows(HWND hWnd) { RECT rect; ::GetClientRect(hWnd, &rect); int xSize = rect.right; int kHeaderSize = 0; int ySize = MyMax(int(rect.bottom - kHeaderSize), 0); if (g_App._rebar) { RECT barRect; g_App._rebar.GetWindowRect(&barRect); kHeaderSize = barRect.bottom - barRect.top; ySize = MyMax(int(rect.bottom - kHeaderSize), 0); } // g_App._headerToolBar.Move(0, 2, xSize, kHeaderSize - 2); RECT rect2 = rect; rect2.bottom = 0; // g_App._headerReBar.SizeToRect(&rect2); if (g_App.NumPanels > 1) { g_App.Panels[0].Move(0, kHeaderSize, g_Splitter.GetPos(), ySize); int xWidth1 = g_Splitter.GetPos() + kSplitterWidth; g_App.Panels[1].Move(xWidth1, kHeaderSize, xSize - xWidth1, ySize); } else { /* int otherPanel = 1 - g_App.LastFocusedPanel; if (g_App.PanelsCreated[otherPanel]) g_App.Panels[otherPanel].Move(0, kHeaderSize, 0, ySize); */ g_App.Panels[g_App.LastFocusedPanel].Move(0, kHeaderSize, xSize, ySize); } }