diff --git a/desmume/src/windows/CWindow.cpp b/desmume/src/windows/CWindow.cpp index 5dcde67ea..1071e439f 100644 --- a/desmume/src/windows/CWindow.cpp +++ b/desmume/src/windows/CWindow.cpp @@ -19,11 +19,18 @@ */ #include "CWindow.h" +#include "main.h" #include "IORegView.h" #include "debug.h" #include "resource.h" #include +#include + +//----------------------------------------------------------------------------- +// The Toolkit - Helpers +//----------------------------------------------------------------------------- + DWORD GetFontQuality() { BOOL aaEnabled = FALSE; @@ -60,6 +67,59 @@ void GetFontSize(HWND hWnd, HFONT hFont, LPSIZE size) ReleaseDC(hWnd, dc); } +void MakeBitmapPseudoTransparent(HBITMAP hBmp, COLORREF cKeyColor, COLORREF cNewKeyColor) +{ + u8 keyr = (cKeyColor >> 16) & 0xFF; + u8 keyg = (cKeyColor >> 8) & 0xFF; + u8 keyb = cKeyColor & 0xFF; + u8 nkeyr = (cNewKeyColor >> 16) & 0xFF; + u8 nkeyg = (cNewKeyColor >> 8) & 0xFF; + u8 nkeyb = cNewKeyColor & 0xFF; + + BITMAP bmp; + BITMAPINFO bmpinfo; + u8* bmpdata = NULL; + + HDC dc = CreateCompatibleDC(NULL); + + GetObject(hBmp, sizeof(BITMAP), &bmp); + + memset(&bmpinfo, 0, sizeof(BITMAPINFO)); + bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFO); + bmpinfo.bmiHeader.biBitCount = 24; + bmpinfo.bmiHeader.biCompression = BI_RGB; + bmpinfo.bmiHeader.biHeight = bmp.bmHeight; + bmpinfo.bmiHeader.biWidth = bmp.bmWidth; + bmpinfo.bmiHeader.biPlanes = bmp.bmPlanes; + bmpdata = new u8[bmp.bmHeight * bmp.bmWidth * 3]; + + GetDIBits(dc, hBmp, 0, bmp.bmHeight, (LPVOID)bmpdata, &bmpinfo, DIB_RGB_COLORS); + + int y2 = 0; + for (int y = 0; y < bmp.bmHeight; y++) + { + for (int x = 0; x < bmp.bmWidth; x++) + { + int idx = y2 + x*3; + u8 r = bmpdata[idx + 0]; + u8 g = bmpdata[idx + 1]; + u8 b = bmpdata[idx + 2]; + + if ((r == keyr) && (g == keyg) && (b == keyb)) + { + bmpdata[idx + 0] = nkeyr; + bmpdata[idx + 1] = nkeyg; + bmpdata[idx + 2] = nkeyb; + } + } + y2 += bmp.bmWidth * 3; + } + + SetDIBits(dc, hBmp, 0, bmp.bmHeight, (LPVOID)bmpdata, &bmpinfo, DIB_RGB_COLORS); + DeleteDC(dc); + delete bmpdata; +} + //----------------------------------------------------------------------------- // Window class handling //----------------------------------------------------------------------------- @@ -266,6 +326,213 @@ void RefreshAllToolWindows() } } +//----------------------------------------------------------------------------- +// The Toolkit - Tooltip API wrapper +//----------------------------------------------------------------------------- + +CToolTip::CToolTip(HWND hParent) +{ + hWnd = CreateWindow(TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_NOPREFIX, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + hParent, NULL, hAppInst, NULL); +} + +void CToolTip::AddToolTip(HWND hCtl, int uID, CRect rcRect, char* text) +{ + TOOLINFO ti; + + memset(&ti, 0, sizeof(TOOLINFO)); + ti.cbSize = sizeof(TOOLINFO); + ti.uFlags = TTF_SUBCLASS; + ti.hwnd = hCtl; + ti.uId = uID; + ti.rect = rcRect.ToMSRect(); + printf("%i %i %i %i\n", rcRect.ToMSRect().top, ti.rect.left, ti.rect.bottom, ti.rect.right); + ti.lpszText = text; + + SendMessage(hWnd, TTM_ADDTOOL, 0, (LPARAM)&ti); +} + +//----------------------------------------------------------------------------- +// The Toolkit - Toolbar API wrapper +//----------------------------------------------------------------------------- + +CToolBar::CToolBar(HWND hParent) +{ + // Create the toolbar + // Note: dropdown buttons look like crap without TBSTYLE_FLAT + hWnd = CreateWindowEx(0, TOOLBARCLASSNAME, + NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | TBSTYLE_FLAT, 0, 0, 0, 0, + hParent, NULL, hAppInst, NULL); + + // Send it a few messages to finish setting it up + SendMessage(hWnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); + SendMessage(hWnd, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS); +} + +CToolBar::~CToolBar() +{ + // Delete all the HBITMAPs we kept stored + for (TBitmapList::iterator it = hBitmaps.begin(); + it != hBitmaps.end(); it++) + { + DeleteObject(it->second.second); + } + + hBitmaps.clear(); +} + +void CToolBar::OnSize() +{ + RECT rc; + int parentwidth; + + GetClientRect(GetParent(hWnd), &rc); + parentwidth = rc.right - rc.left; + + // When there's not enough space to fit all the buttons in one line, + // we have to add the 'linebreaks' ourselves + int numbtns = SendMessage(hWnd, TB_BUTTONCOUNT, 0, 0); + int curwidth = 0; + + for (int i = 0; i < numbtns; i++) + { + SendMessage(hWnd, TB_GETITEMRECT, i, (LPARAM)&rc); + curwidth += (rc.right - rc.left); + + if (i > 0) + { + TBBUTTON btn; + TBBUTTONINFO btninfo; + + // Retrieve the command ID of the button just behind the current one + // if it's a separator, then try the button behind it + SendMessage(hWnd, TB_GETBUTTON, i-1, (LPARAM)&btn); + if (btn.idCommand == -1) + SendMessage(hWnd, TB_GETBUTTON, i-2, (LPARAM)&btn); + + // Add/remove the TBSTATE_WRAP style if needed + btninfo.cbSize = sizeof(TBBUTTONINFO); + btninfo.dwMask = TBIF_STATE; + SendMessage(hWnd, TB_GETBUTTONINFO, btn.idCommand, (LPARAM)&btninfo); + + btninfo.dwMask = TBIF_STATE; + if (curwidth > parentwidth) btninfo.fsState |= TBSTATE_WRAP; + else btninfo.fsState &= ~TBSTATE_WRAP; + SendMessage(hWnd, TB_SETBUTTONINFO, btn.idCommand, (LPARAM)&btninfo); + + if (curwidth > parentwidth) curwidth = 0; + } + } + + SetWindowPos(hWnd, NULL, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + SWP_NOZORDER | SWP_NOMOVE); +} + +void CToolBar::AppendButton(int uID, int uBitmapID, DWORD dwState, bool bDropdown) +{ + HBITMAP hbmp; + TBADDBITMAP bmp; + TBBUTTON btn; + + // Get the bitmap and replace the key color (magenta) with the right color + hbmp = LoadBitmap(hAppInst, MAKEINTRESOURCE(uBitmapID)); + MakeBitmapPseudoTransparent(hbmp, RGB(255, 0, 255), GetSysColor(COLOR_BTNFACE)); + + // Add the bitmap to the toolbar's image list + bmp.hInst = NULL; + bmp.nID = (UINT_PTR)hbmp; + + int bmpid = SendMessage(hWnd, TB_ADDBITMAP, 1, (LPARAM)&bmp); + + // Save the bitmap (if it gets deleted, the toolbar is too) + hBitmaps[uBitmapID] = TBitmapPair(bmpid, hbmp); + + // And finally add the button + memset(&btn, 0, sizeof(TBBUTTON)); + btn.fsStyle = bDropdown ? TBSTYLE_DROPDOWN : TBSTYLE_BUTTON; + btn.fsState = dwState; + btn.idCommand = uID; + btn.iString = -1; + btn.iBitmap = bmpid; + + SendMessage(hWnd, TB_ADDBUTTONS, 1, (LPARAM)&btn); +} + +void CToolBar::AppendSeparator() +{ + TBBUTTON btn; + + memset(&btn, 0, sizeof(TBBUTTON)); + btn.fsStyle = TBSTYLE_SEP; + btn.idCommand = -1; + btn.iString = -1; + + SendMessage(hWnd, TB_ADDBUTTONS, 1, (LPARAM)&btn); +} + +void CToolBar::ChangeButtonBitmap(int uID, int uBitmapID) +{ + int bmpid = 0; + + // If we don't already have the bitmap, retrieve it, + // adapt it and store it in the list + TBitmapList::iterator it = hBitmaps.find(uBitmapID); + + if (it == hBitmaps.end()) + { + HBITMAP hbmp; + TBADDBITMAP bmp; + + hbmp = LoadBitmap(hAppInst, MAKEINTRESOURCE(uBitmapID)); + MakeBitmapPseudoTransparent(hbmp, RGB(255, 0, 255), GetSysColor(COLOR_BTNFACE)); + + bmp.hInst = NULL; + bmp.nID = (UINT_PTR)hbmp; + + bmpid = SendMessage(hWnd, TB_ADDBITMAP, 1, (LPARAM)&bmp); + + hBitmaps[uBitmapID] = TBitmapPair(bmpid, hbmp); + } + else + bmpid = hBitmaps[uBitmapID].first; + + // Finally change the bitmap + SendMessage(hWnd, TB_CHANGEBITMAP, uID, MAKELPARAM(bmpid, 0)); +} + +void CToolBar::EnableButtonDropdown(int uID, bool bDropdown) +{ + TBBUTTONINFO btninfo; + + memset(&btninfo, 0, sizeof(TBBUTTONINFO)); + btninfo.cbSize = sizeof(TBBUTTONINFO); + btninfo.dwMask = TBIF_STYLE; + + SendMessage(hWnd, TB_GETBUTTONINFO, uID, (LPARAM)&btninfo); + + btninfo.dwMask = TBIF_STYLE; + if (bDropdown) + { + btninfo.fsStyle &= ~TBSTYLE_BUTTON; + btninfo.fsStyle |= TBSTYLE_DROPDOWN; + } + else + { + btninfo.fsStyle |= TBSTYLE_BUTTON; + btninfo.fsStyle &= ~TBSTYLE_DROPDOWN; + } + + SendMessage(hWnd, TB_SETBUTTONINFO, uID, (LPARAM)&btninfo); +} + +int CToolBar::GetHeight() +{ + RECT rc; GetWindowRect(hWnd, &rc); + return rc.bottom - rc.top; +} + WINCLASS::WINCLASS(LPSTR rclass, HINSTANCE hInst) { @@ -289,6 +556,9 @@ bool WINCLASS::create(LPSTR caption, int x, int y, int width, int height, int st if (hwnd != NULL) return false; hwnd = CreateWindow(regclass, caption, style, x, y, width, height, NULL, menu, hInstance, NULL); +// hwnd = CreateWindowEx(WS_EX_LAYERED, regclass, caption, style, x, y, width, height, NULL, menu, hInstance, NULL); + //SetLayeredWindowAttributes(hwnd, 0, 254, LWA_ALPHA); + // if (hwnd != NULL) return true; return false; @@ -363,6 +633,8 @@ void WINCLASS::sizingMsg(WPARAM wParam, LPARAM lParam, LONG keepRatio) int _minWidth, _minHeight; + int tbheight = MainWindowToolbar->GetHeight(); + RECT adjr; SetRect(&adjr,0,0,minWidth,minHeight); MyAdjustWindowRectEx(&adjr,hwnd); @@ -371,11 +643,11 @@ void WINCLASS::sizingMsg(WPARAM wParam, LPARAM lParam, LONG keepRatio) SetRect(&frameInfo,0,0,0,0); MyAdjustWindowRectEx(&frameInfo,hwnd); int frameWidth = frameInfo.right-frameInfo.left; - int frameHeight = frameInfo.bottom-frameInfo.top; + int frameHeight = frameInfo.bottom-frameInfo.top + tbheight; // Calculate the minimum size in pixels _minWidth = adjr.right-adjr.left; - _minHeight = adjr.bottom-adjr.top; + _minHeight = adjr.bottom-adjr.top + tbheight; /* Clamp the size to the minimum size (256x384) */ rect->right = (rect->left + std::max(_minWidth, (int)(rect->right - rect->left))); @@ -461,6 +733,8 @@ void WINCLASS::sizingMsg(WPARAM wParam, LPARAM lParam, LONG keepRatio) void WINCLASS::setClientSize(int width, int height) { + height += MainWindowToolbar->GetHeight(); + //yep, do it twice, once in case the menu wraps, and once to accomodate that wrap for(int i=0;i<2;i++) { diff --git a/desmume/src/windows/CWindow.h b/desmume/src/windows/CWindow.h index 629cebdd2..df2045c2d 100644 --- a/desmume/src/windows/CWindow.h +++ b/desmume/src/windows/CWindow.h @@ -25,12 +25,40 @@ #include #include +#include #include using namespace std; extern CRITICAL_SECTION win_execute_sync; +//----------------------------------------------------------------------------- +// The Toolkit - RECT wrapper +//----------------------------------------------------------------------------- + +class CRect +{ +public: + CRect(int x, int y, int width, int height) + { + rcRect.left = x; rcRect.top = y; + rcRect.right = x + width; + rcRect.bottom = y + height; + } + CRect(RECT rc) + { + memcpy(&rcRect, &rc, sizeof(RECT)); + //rcRect = rc; + } + + ~CRect() {} + + RECT ToMSRect() { return rcRect; } + +private: + RECT rcRect; +}; + // GetFontQuality() // Returns a font quality value that can be passed to // CreateFont(). The value depends on whether font @@ -40,6 +68,12 @@ DWORD GetFontQuality(); int DrawText(HDC hDC, char* text, int X, int Y, int Width, int Height, UINT format); void GetFontSize(HWND hWnd, HFONT hFont, LPSIZE size); +// MakeBitmapPseudoTransparent(HBITMAP hBmp, COLORREF cKeyColor, COLORREF cNewKeyColor) +// Replaces the RGB color cKeyColor with cNewKeyColor in the bitmap hBmp. +// For use with toolbars and such. Replace a key color (like magenta) with the right +// system color to make the bitmap pseudo-transparent. +void MakeBitmapPseudoTransparent(HBITMAP hBmp, COLORREF cKeyColor, COLORREF cNewKeyColor); + //----------------------------------------------------------------------------- // Window class handling //----------------------------------------------------------------------------- @@ -138,6 +172,64 @@ void CloseAllToolWindows(); // Called once per frame when the emu is running. void RefreshAllToolWindows(); +//----------------------------------------------------------------------------- +// The Toolkit - Tooltip API wrapper +//----------------------------------------------------------------------------- + +class CToolTip +{ +public: + CToolTip(HWND hParent); + ~CToolTip() {} + + HWND GetHWnd() { return hWnd; } + + void AddToolTip(HWND hCtl, int uID, CRect rcRect, char* text); + +private: + HWND hWnd; +}; + +//----------------------------------------------------------------------------- +// The Toolkit - Toolbar API wrapper +//----------------------------------------------------------------------------- + +class CToolBar +{ +public: + CToolBar(HWND hParent); + ~CToolBar(); + + HWND GetHWnd() { return hWnd; } + + void OnSize(); + + void AppendButton(int uID, int uBitmapID, DWORD dwState, bool bDropdown); + void AppendSeparator(); + + void EnableButton(int uID, bool bEnable) { + SendMessage(hWnd, TB_ENABLEBUTTON, uID, bEnable ? TRUE:FALSE); } + void CheckButton(int uID, bool bCheck) { + SendMessage(hWnd, TB_CHECKBUTTON, uID, bCheck ? TRUE:FALSE); } + + void ChangeButtonBitmap(int uID, int uBitmapID); + + void EnableButtonDropdown(int uID, bool bDropdown); + + void SetToolTip(CToolTip tt); + + int GetHeight(); + +private: + HWND hWnd; + // We have to keep the bitmaps here because destroying them + // directly after use would also destroy the toolbar. + // They'll be destroyed when the CToolBar destructor is called. + typedef pair TBitmapPair; + typedef map TBitmapList; + TBitmapList hBitmaps; +}; + class WINCLASS { @@ -164,6 +256,12 @@ public: HWND getHWnd(); + CRect GetRect() + { + RECT rc; GetWindowRect(hwnd, &rc); + return CRect(rc); + } + void setMinSize(int width, int height); enum // keepRatio flags diff --git a/desmume/src/windows/bitmaps/IDB_FRAMEADVANCE.bmp b/desmume/src/windows/bitmaps/IDB_FRAMEADVANCE.bmp new file mode 100644 index 000000000..9d7144687 Binary files /dev/null and b/desmume/src/windows/bitmaps/IDB_FRAMEADVANCE.bmp differ diff --git a/desmume/src/windows/bitmaps/IDB_OPEN.bmp b/desmume/src/windows/bitmaps/IDB_OPEN.bmp new file mode 100644 index 000000000..ba7073f01 Binary files /dev/null and b/desmume/src/windows/bitmaps/IDB_OPEN.bmp differ diff --git a/desmume/src/windows/bitmaps/IDB_PAUSE.bmp b/desmume/src/windows/bitmaps/IDB_PAUSE.bmp new file mode 100644 index 000000000..857d800a9 Binary files /dev/null and b/desmume/src/windows/bitmaps/IDB_PAUSE.bmp differ diff --git a/desmume/src/windows/bitmaps/IDB_PLAY.bmp b/desmume/src/windows/bitmaps/IDB_PLAY.bmp new file mode 100644 index 000000000..d8268f10e Binary files /dev/null and b/desmume/src/windows/bitmaps/IDB_PLAY.bmp differ diff --git a/desmume/src/windows/bitmaps/IDB_RESET.bmp b/desmume/src/windows/bitmaps/IDB_RESET.bmp new file mode 100644 index 000000000..762a84468 Binary files /dev/null and b/desmume/src/windows/bitmaps/IDB_RESET.bmp differ diff --git a/desmume/src/windows/bitmaps/IDB_STOP.bmp b/desmume/src/windows/bitmaps/IDB_STOP.bmp new file mode 100644 index 000000000..879bc2bc4 Binary files /dev/null and b/desmume/src/windows/bitmaps/IDB_STOP.bmp differ diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp index 3d4006550..5257ac8ec 100644 --- a/desmume/src/windows/main.cpp +++ b/desmume/src/windows/main.cpp @@ -88,13 +88,7 @@ #include "pathsettings.h" #include "colorctrl.h" #include "ginfo.h" -#include "IORegView.h" -#include "palView.h" -#include "tileView.h" -#include "oamView.h" -#include "mapview.h" -#include "matrixview.h" -#include "lightview.h" +#include "tools.h" #include "gbaslot_config.h" #include "cheatsWin.h" #include "memView.h" @@ -102,10 +96,7 @@ #include "FirmConfig.h" #include "AboutBox.h" #include "replay.h" -#include "ramwatch.h" -#include "ram_search.h" #include "aviout.h" -#include "soundView.h" using namespace std; @@ -181,6 +172,7 @@ static bool _cheatsDisabled = false; void UpdateHotkeyAssignments(); //Appends hotkey mappings to corresponding menu items HMENU mainMenu = NULL; //Holds handle to the main DeSmuME menu +CToolBar* MainWindowToolbar; DWORD hKeyInputTimer; @@ -536,7 +528,7 @@ void UnscaleScreenCoords(s32& x, s32& y) RECT r; GetNdsScreenRect(&r); - int winwidth = (r.right-r.left), winheight = (r.bottom-r.top); + int winwidth = (r.right-r.left), winheight = (r.bottom-r.top) - MainWindowToolbar->GetHeight(); x -= r.left; y -= r.top; @@ -914,16 +906,19 @@ void UpdateWndRects(HWND hwnd) defHeight += video.scaledscreengap(); float ratio; int oneScreenHeight, gapHeight; + int tbheight; GetClientRect(hwnd, &rc); if(maximized) rc = FullScreenRect; + tbheight = MainWindowToolbar->GetHeight(); + if (video.layout == 1) { - wndWidth = (rc.bottom - rc.top); + wndWidth = (rc.bottom - rc.top) - tbheight; wndHeight = (rc.right - rc.left); ratio = ((float)wndHeight / (float)defHeight); @@ -957,7 +952,7 @@ void UpdateWndRects(HWND hwnd) if (video.layout == 2) { - wndWidth = (rc.bottom - rc.top); + wndWidth = (rc.bottom - rc.top) - tbheight; wndHeight = (rc.right - rc.left); ratio = ((float)wndHeight / (float)defHeight); @@ -980,13 +975,13 @@ void UpdateWndRects(HWND hwnd) { if((video.rotation == 90) || (video.rotation == 270)) { - wndWidth = (rc.bottom - rc.top); + wndWidth = (rc.bottom - rc.top) - tbheight; wndHeight = (rc.right - rc.left); } else { wndWidth = (rc.right - rc.left); - wndHeight = (rc.bottom - rc.top); + wndHeight = (rc.bottom - rc.top) - tbheight; } ratio = ((float)wndHeight / (float)defHeight); @@ -1064,6 +1059,13 @@ void UpdateWndRects(HWND hwnd) GapRect.bottom = (rc.top + oneScreenHeight + gapHeight); } } + + MainScreenRect.top += tbheight; + MainScreenRect.bottom += tbheight; + SubScreenRect.top += tbheight; + SubScreenRect.bottom += tbheight; + GapRect.top += tbheight; + GapRect.bottom += tbheight; } void FixAspectRatio(); @@ -1679,7 +1681,7 @@ static void StepRunLoop_Core() static void StepRunLoop_Paused() { paused = TRUE; - Sleep(100); + Sleep(50); // periodically update single-core OSD when paused and in the foreground if(CommonSettings.single_core() && GetActiveWindow() == mainLoopData.hwnd) @@ -1881,6 +1883,8 @@ void NDS_Pause(bool showMsg) SPU_Pause(1); while (!paused) {} if (showMsg) INFO("Emulation paused\n"); + + MainWindowToolbar->ChangeButtonBitmap(IDM_PAUSE, IDB_PLAY); } } @@ -1893,6 +1897,8 @@ void NDS_UnPause(bool showMsg) execute = TRUE; SPU_Pause(0); if (showMsg) INFO("Emulation unpaused\n"); + + MainWindowToolbar->ChangeButtonBitmap(IDM_PAUSE, IDB_PAUSE); } } @@ -2934,7 +2940,7 @@ void SetRotate(HWND hwnd, int rot, bool user) GetClientRect(hwnd, &rc); oldwidth = (rc.right - rc.left); - oldheight = (rc.bottom - rc.top); + oldheight = (rc.bottom - rc.top) - MainWindowToolbar->GetHeight(); newwidth = oldwidth; newheight = oldheight; @@ -3138,6 +3144,13 @@ static BOOL OpenCore(const char* filename) { romloaded = TRUE; Unpause(); + + // Update the toolbar + MainWindowToolbar->EnableButton(IDM_PAUSE, true); + MainWindowToolbar->EnableButton(IDM_CLOSEROM, true); + MainWindowToolbar->EnableButton(IDM_RESET, true); + MainWindowToolbar->ChangeButtonBitmap(IDM_PAUSE, IDB_PAUSE); + return TRUE; } else return FALSE; @@ -3227,6 +3240,11 @@ void CloseRom() execute = false; Hud.resetTransient(); NDS_Reset(); + + MainWindowToolbar->EnableButton(IDM_PAUSE, false); + MainWindowToolbar->EnableButton(IDM_CLOSEROM, false); + MainWindowToolbar->EnableButton(IDM_RESET, false); + MainWindowToolbar->ChangeButtonBitmap(IDM_PAUSE, IDB_PLAY); } int GetInitialModifiers(int key) // async version for input thread @@ -3536,6 +3554,7 @@ void SaveWindowSize(HWND hwnd) if(IsZoomed(hwnd)) return; RECT rc; GetClientRect(hwnd, &rc); + rc.top += MainWindowToolbar->GetHeight(); WritePrivateProfileInt("Video", "Window width", (rc.right - rc.left), IniName); WritePrivateProfileInt("Video", "Window height", (rc.bottom - rc.top), IniName); } @@ -3742,6 +3761,14 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM path.ReadPathSettings(); pausedByMinimize = FALSE; UpdateScreenRects(); + + MainWindowToolbar = new CToolBar(hwnd); + MainWindowToolbar->AppendButton(IDM_OPEN, IDB_OPEN, TBSTATE_ENABLED, false); + MainWindowToolbar->AppendSeparator(); + MainWindowToolbar->AppendButton(IDM_PAUSE, IDB_PLAY, 0, false); + MainWindowToolbar->AppendButton(IDM_CLOSEROM, IDB_STOP, 0, false); + MainWindowToolbar->AppendButton(IDM_RESET, IDB_RESET, 0, false); + return 0; } case WM_DESTROY: @@ -3791,6 +3818,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM } else NDS_UnPause(); + delete MainWindowToolbar; return 0; } case WM_MOVING: @@ -3860,18 +3888,16 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM minX = video.rotatedwidthgap(); minY = video.rotatedheightgap(); } - else - if (video.layout == 1) - { - minX = video.rotatedwidthgap() * 2; - minY = video.rotatedheightgap() / 2; - } - else - if (video.layout == 2) - { - minX = video.rotatedwidthgap(); - minY = video.rotatedheightgap() / 2; - } + else if (video.layout == 1) + { + minX = video.rotatedwidthgap() * 2; + minY = video.rotatedheightgap() / 2; + } + else if (video.layout == 2) + { + minX = video.rotatedwidthgap(); + minY = video.rotatedheightgap() / 2; + } if(verticalDrag && !sideways && SeparationBorderDrag && video.layout == 0) { @@ -3890,6 +3916,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM forceRatioFlags |= WINCLASS::KEEPX; forceRatioFlags |= WINCLASS::KEEPY; } + MainWindow->setMinSize(minX, minY); } @@ -3907,20 +3934,22 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM int wndWidth, wndHeight, wndHeightGapless; if(sideways) { - wndWidth = (rc.bottom - rc.top); + wndWidth = (rc.bottom - rc.top) - MainWindowToolbar->GetHeight(); wndHeight = (rc.right - rc.left); wndHeightGapless = (MainScreenRect.right - MainScreenRect.left) + (SubScreenRect.right - SubScreenRect.left); } else { wndWidth = (rc.right - rc.left); - wndHeight = (rc.bottom - rc.top); + wndHeight = (rc.bottom - rc.top) - MainWindowToolbar->GetHeight(); wndHeightGapless = (MainScreenRect.bottom - MainScreenRect.top) + (SubScreenRect.bottom - SubScreenRect.top); } + if(ForceRatio) - video.screengap = wndHeight * video.width / wndWidth - video.height; + video.screengap = (wndHeight * video.width / wndWidth - video.height); else video.screengap = wndHeight * video.height / wndHeightGapless - video.height; + UpdateWndRects(MainWindow->getHWnd()); } } @@ -4030,7 +4059,7 @@ DOKEYDOWN: } UpdateWndRects(hwnd); - + MainWindowToolbar->OnSize(); } break; } @@ -4160,7 +4189,7 @@ DOKEYDOWN: SetCapture(hwnd); s32 x = (s32)((s16)LOWORD(lParam)); - s32 y = (s32)((s16)HIWORD(lParam)); + s32 y = (s32)((s16)HIWORD(lParam)) - MainWindowToolbar->GetHeight(); UnscaleScreenCoords(x,y); @@ -4216,13 +4245,15 @@ DOKEYDOWN: if(wParam >= recentRoms_baseid && wParam <= recentRoms_baseid + MAX_RECENT_ROMS - 1) { int x = wParam - recentRoms_baseid; - OpenRecentROM(x); + OpenRecentROM(x); + return 0; } else if(wParam == recentRoms_clearid) { /* Clear all the recent ROMs */ - if(IDOK == MessageBox(hwnd, "OK to clear recent ROMs list?","DeSmuME",MB_OKCANCEL)) + if(IDOK == MessageBox(hwnd, "Are you sure you want to clear the recent ROMs list?", "DeSmuME", MB_OKCANCEL | MB_ICONQUESTION)) ClearRecentRoms(); + return 0; } if(wParam >= IDD_LUARECENT_RESERVE_START && @@ -4240,6 +4271,8 @@ DOKEYDOWN: SendDlgItemMessage(hDlg,IDC_EDIT_LUAPATH,WM_SETTEXT,0,(LPARAM)temp); } } + + return 0; } if(wParam >= IDC_LUASCRIPT_RESERVE_START && @@ -4248,6 +4281,8 @@ DOKEYDOWN: unsigned int index = wParam - IDC_LUASCRIPT_RESERVE_START; if(LuaScriptHWnds.size() > index) SetForegroundWindow(LuaScriptHWnds[index]); + + return 0; } } @@ -5160,7 +5195,41 @@ DOKEYDOWN: } return 0; + default: + return 0; } + + case WM_NOTIFY: + { + NMHDR nmhdr = *(NMHDR*)lParam; + switch (nmhdr.code) + { + case TBN_DROPDOWN: + { + NMTOOLBAR nmtb = *(NMTOOLBAR*)lParam; + + if (nmtb.iItem == IDM_OPEN) + { + // Get the recent roms menu (too lazy to make a new menu :P ) + HMENU _rrmenu = GetSubMenu(recentromsmenu, 0); + + // Here are the coordinates we want the recent roms menu to popup at + POINT pt; + pt.x = nmtb.rcButton.left; + pt.y = nmtb.rcButton.bottom; + + // Convert the coordinates to screen coordinates + ClientToScreen(hwnd, &pt); + + // Finally show the menu; once the user chose a ROM, we'll get a WM_COMMAND + TrackPopupMenu(_rrmenu, 0, pt.x, pt.y, 0, hwnd, NULL); + return TBDDRET_DEFAULT; + } + } + return 0; + } + } + return 0; } return DefWindowProc (hwnd, message, wParam, lParam); } diff --git a/desmume/src/windows/main.h b/desmume/src/windows/main.h index ededb7550..304afcd99 100644 --- a/desmume/src/windows/main.h +++ b/desmume/src/windows/main.h @@ -5,6 +5,7 @@ extern WINCLASS *MainWindow; extern HINSTANCE hAppInst; extern HMENU mainMenu; //Holds handle to the main DeSmuME menu +extern CToolBar* MainWindowToolbar; extern volatile bool execute, paused; void NDS_Pause(bool showMsg = true); diff --git a/desmume/src/windows/recentroms.cpp b/desmume/src/windows/recentroms.cpp index 463732ea5..6eb7465c7 100644 --- a/desmume/src/windows/recentroms.cpp +++ b/desmume/src/windows/recentroms.cpp @@ -32,7 +32,7 @@ #include std::vector RecentRoms; //The list of recent ROM filenames -static HMENU recentromsmenu; //Handle to the recent ROMs submenu +HMENU recentromsmenu; //Handle to the recent ROMs submenu void PopulateRecentRomsMenu() { @@ -181,6 +181,7 @@ void ClearRecentRoms() RecentRoms.clear(); SaveRecentRoms(); PopulateRecentRomsMenu(); + MainWindowToolbar->EnableButtonDropdown(IDM_OPEN, false); } @@ -221,6 +222,7 @@ void UpdateRecentRoms(const char* filename) PopulateRecentRomsMenu(); SaveRecentRoms(); + MainWindowToolbar->EnableButtonDropdown(IDM_OPEN, true); } @@ -229,4 +231,5 @@ void InitRecentRoms() recentromsmenu = LoadMenu(hAppInst, MAKEINTRESOURCE(RECENTROMS)); LoadRecentRoms(); PopulateRecentRomsMenu(); + MainWindowToolbar->EnableButtonDropdown(IDM_OPEN, !RecentRoms.empty()); } diff --git a/desmume/src/windows/recentroms.h b/desmume/src/windows/recentroms.h index 419605fdb..2e32bfcae 100644 --- a/desmume/src/windows/recentroms.h +++ b/desmume/src/windows/recentroms.h @@ -32,6 +32,7 @@ static const unsigned int recentRoms_clearid = IDM_RECENT_RESERVED0; // ID for static const unsigned int recentRoms_baseid = IDM_RECENT_RESERVED1; //Base identifier for the recent ROMs items extern std::vector RecentRoms; //The list of recent ROM filenames +extern HMENU recentromsmenu; // The handle to the recent ROMs menu void UpdateRecentRoms(const char* filename); void InitRecentRoms(); diff --git a/desmume/src/windows/resource.h b/desmume/src/windows/resource.h index a58ab7ce0..3fdd94a36 100644 --- a/desmume/src/windows/resource.h +++ b/desmume/src/windows/resource.h @@ -11,19 +11,25 @@ #define IDC_SETPNUM 105 #define IDC_SCROLLER 106 #define IDD_SOUNDSETTINGS 106 +#define IDB_FRAMEADVANCE 106 #define IDC_GO 107 #define IDC_AUTO_UPDATE 108 +#define IDB_OPEN 108 #define IDM_MEMORY 109 #define IDM_DISASSEMBLER 110 +#define IDB_PAUSE 110 #define IDD_3DSETTINGS 111 #define IDM_GAME_INFO 111 +#define IDB_PLAY 112 #define IDD_GBASLOT 113 #define IDM_PAUSE 113 #define IDD_GBASLOT_CFLASH 114 #define IDM_RESET 114 +#define IDB_RESET 114 #define IDD_CHEAT_SEARCH_VIEW 115 #define IDM_IOREG 115 #define IDD_CHEAT_LIST 116 +#define IDB_STOP 116 #define IDD_CHEAT_ADD 117 #define IDM_PAL 117 #define IDM_TILE 118 @@ -341,6 +347,7 @@ #define IDC_SYNCHMETHOD_P 1018 #define IDC_VISIBLE 1019 #define IDC_USEPHYSICAL 1019 +#define IDC_SPLIT1 1021 #define IDC_DEFAULT 1027 #define IDC_3DCORE 1028 #define IDC_TXT_COMPILED 1029 @@ -796,9 +803,9 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 106 +#define _APS_NEXT_RESOURCE_VALUE 118 #define _APS_NEXT_COMMAND_VALUE 40014 -#define _APS_NEXT_CONTROL_VALUE 1020 +#define _APS_NEXT_CONTROL_VALUE 1022 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/desmume/src/windows/resources.rc b/desmume/src/windows/resources.rc index 6af8c86ba..96d313d75 100644 Binary files a/desmume/src/windows/resources.rc and b/desmume/src/windows/resources.rc differ