From 47c8545beeb60b174e7312c3fc97756334933697 Mon Sep 17 00:00:00 2001 From: luigi__ Date: Tue, 22 Dec 2009 17:25:32 +0000 Subject: [PATCH] Windows port: Add a toolbar to the main window. Unfinished, lacks some tooltips and some other buttons. But atleast the big part is here. --- desmume/src/windows/CWindow.cpp | 278 +++++++++++++++++- desmume/src/windows/CWindow.h | 98 ++++++ .../src/windows/bitmaps/IDB_FRAMEADVANCE.bmp | Bin 0 -> 822 bytes desmume/src/windows/bitmaps/IDB_OPEN.bmp | Bin 0 -> 822 bytes desmume/src/windows/bitmaps/IDB_PAUSE.bmp | Bin 0 -> 822 bytes desmume/src/windows/bitmaps/IDB_PLAY.bmp | Bin 0 -> 822 bytes desmume/src/windows/bitmaps/IDB_RESET.bmp | Bin 0 -> 822 bytes desmume/src/windows/bitmaps/IDB_STOP.bmp | Bin 0 -> 822 bytes desmume/src/windows/main.cpp | 141 ++++++--- desmume/src/windows/main.h | 1 + desmume/src/windows/recentroms.cpp | 5 +- desmume/src/windows/recentroms.h | 1 + desmume/src/windows/resource.h | 11 +- desmume/src/windows/resources.rc | Bin 889126 -> 891118 bytes 14 files changed, 494 insertions(+), 41 deletions(-) create mode 100644 desmume/src/windows/bitmaps/IDB_FRAMEADVANCE.bmp create mode 100644 desmume/src/windows/bitmaps/IDB_OPEN.bmp create mode 100644 desmume/src/windows/bitmaps/IDB_PAUSE.bmp create mode 100644 desmume/src/windows/bitmaps/IDB_PLAY.bmp create mode 100644 desmume/src/windows/bitmaps/IDB_RESET.bmp create mode 100644 desmume/src/windows/bitmaps/IDB_STOP.bmp 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 0000000000000000000000000000000000000000..9d71446872d75b63517ebfdda0da9fb78a1ac9c5 GIT binary patch literal 822 zcmZ?rHDhJ~12Z700mK4O%*Y@C7H0s;AK`;whyVk_e}?}gp_PFun^K+M+`J6Y_5H(} z-4zjMX0`wR{tc@+`^#J&Z7N(FtZ`;eA5g)kXAid|=^d$a-I5dd>gst+E&B^?{y&}e zYg|}78BNRHZ1exeivJ%k`gfw}_C$|`4q_Xl z)c>BT{C}nPHt{4N?CWyZvA6{(phX|8+sX)<&EzFx(s>^PtoE|GI$x+u~o(58f0ax2G=S z>+9!x^IZNPYyQ7I_y6|1|0i1CY%JZGY<9HR>C4vq|EHS&o$kBX8MZ1||Nf!vkRaMy z?DPM|ivL#^{=K>O+U$b)4lbN^QmaY!Byt;Y;P~_v2`=q{RKAa`Z3_V)as_Ydwsq<(&Sf2cL<@`{;%fB(W%Ooj*mFXrch literal 0 HcmV?d00001 diff --git a/desmume/src/windows/bitmaps/IDB_OPEN.bmp b/desmume/src/windows/bitmaps/IDB_OPEN.bmp new file mode 100644 index 0000000000000000000000000000000000000000..ba7073f01f960d45328c3330b3f346d0cdef230c GIT binary patch literal 822 zcmaiyT}YE*6vvjgO(IU0>RoleJkK@ORdJ>Eg1ShfF;g#xi? z6Sd_e25&{~3f& zqx&QzJA#Mct48NR)tXN=>$`TdA8$eY8iudnX(NWtW8f_M>d<=%UB}d_0)*^Y|E7`s zi949MjaRpjxPj4Dj9f+R5~2-suWHlNY}W6nVSlCvGrgD&VbX_p532VURhAT6nLXxR zJFNSPO*`{+Ivwx-sGj{VaprRj${^%$r2XFVvWDE)TUf~cGZ*{0(d}(R@+Z_;d{dZ3 z8AusQOW1$Yjz|NKtRd8T89!vmW0-x(e2gQxRBkk|FVh0VV|=1IzyLva6O<8*Nl0`t z&;3}MGFKScpMRYLKuuq>1MkCl;YWf-Bn)?8Vbol4fc@N{PQ-ID;Pv3wSIkXeewvwk zi=<|$G=CrOBVjG{qBKpD0)9RwwSv@YnicvgGnq0^^xt~)_zAcBy35t_mo|^*Ni6mo Dw_W)T literal 0 HcmV?d00001 diff --git a/desmume/src/windows/bitmaps/IDB_PAUSE.bmp b/desmume/src/windows/bitmaps/IDB_PAUSE.bmp new file mode 100644 index 0000000000000000000000000000000000000000..857d800a9dfbc06cb25b080612477268cda442e1 GIT binary patch literal 822 zcmbV}Ur1A77{*U@A3+vDAaoIGT2k(8Qz%#vM3nCTs!4@&xY(9E)nyKxr`8$~5k$DQ z^eSo`H$BU9KB0|yj?rBdSrioA%!tkm`bR|d^tqL|1zq&v$68e(7C#%TGbDR5e~O2BNlbUs`B<3Zucxd00zrfi3X)Wm&)6e2nB2z zcYDsW10Mt|rtvZJ{^2F*q;(mlkLjTGjl$zo2IVw9XJ-ONv9|^D7w|ZW`Ish!WX`sd zC#RexVE|7r;?a3Lixcm5(X|;xKME&M3~0ApGFPKdPCH5|3zQ)8J}3clY>Q~ygb6c* z9%Rkhb(74QYxF69Wf!s*2;G>p5OzjP68=CHD0do<%~3B&)?*Wv;tMe~E9VBt~^e>509n z{~!E6{8aTj{`hG?QjY{nyB2G!_e1lEv`{A%KZYegG*7{fv>g*p?b=>B^jDsjO>~4i zHe{USNTYbD32Fqh!%%tcw!eN~bid>MnB!3##{F~Tc$;{X#mgLCOySjZIe%5=>^1pt zt_3khM|eJo*Anq{iTx&gdyB6N`2KG3NkJN{;iaH$;lUJsl<}p6pJg(*UvTU5Lw)%n gPd@Cu>p!4G11t6C;#|(RuMqa$JKL8JdxT#07dR@|R{#J2 literal 0 HcmV?d00001 diff --git a/desmume/src/windows/bitmaps/IDB_PLAY.bmp b/desmume/src/windows/bitmaps/IDB_PLAY.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d8268f10e563355409e3c8de0de82a512ddc21b4 GIT binary patch literal 822 zcmah`>rc{Q6sGkL^wF)&+Pc?TLyVCQbkbrY#4e*6GZ8{!32tuPTlT@)+S=NhHq%5! zr(j+Pc>USDC0J1Ssf@vAil%rP+lNe^k_a2A!1jwnSHlgd% zPI^K=>4_~Zrc^|>4bMu^%0(+Lji)@&pi^TZx&@&}Z1;s6qT&1O-HDYLk>$cHK{Fdo z96ZTDGacux!@z+tfB7-{t!ArLRY=ZkN8d@NpJq4qH_?|ILI)3~qoKwEmpYedOPKjp z=n$Yyfc7G^7c*V}10SYiu$}wfB5_ph9H= k1>frjwUn;RZ#AtY5}9mvJRs*#dg&}Rkcj=vX0t250IB`;#{d8T literal 0 HcmV?d00001 diff --git a/desmume/src/windows/bitmaps/IDB_RESET.bmp b/desmume/src/windows/bitmaps/IDB_RESET.bmp new file mode 100644 index 0000000000000000000000000000000000000000..762a84468a811c931251f6e157707468a5d64455 GIT binary patch literal 822 zcmaiyT}YE*6vr3cM>l2EMJ_KY>|%4ysrf}|xxisv)S$L^A4+A;CCh|-YZi!77a=5S zngbD=WzFU0`f$rRrxMDZzkaT z7d-XRYp09)wdvEtcic4+qRS$>)S1uzjr?L{cBtW&O_dz%P^^sK#kVGg&LbKDDLM2P zzw~RtZ))#Vrh99TE)D81LW8-2x7V1;EOP!JQFCMY36H~iN$l1p{_H*t=LNh_z$!zZ z45WmqI82mWrz|cq8DQ&~n+Q1cMg0^v+>iy!Nth%sit$hk;|Un^VL8K;i-rJVMs=E5}K0G zEI?C?8u{qV`@`>iEaeTC#xJzypfd-}d^GYl@H`mV`-Q9ZP`jrC@5gM9EXp+B_0;7j zQglmT$b=yqhMaY^Wx_0F%F|fhd2YvSaEyKLeE7TPUbU6t2k*;QTr^&3V50DpLXUEF z$ zYN$pw?=>Ox8h#_bI+$uHsVE>7`5SpQi|z8et_QuvxxUW2rMUpG=&mht>gBGR@=fM# kVJ7UUukO8FDo0XZr0mFOgUjP6A literal 0 HcmV?d00001 diff --git a/desmume/src/windows/bitmaps/IDB_STOP.bmp b/desmume/src/windows/bitmaps/IDB_STOP.bmp new file mode 100644 index 0000000000000000000000000000000000000000..879bc2bc44f305f90532f24616d0e0141898a5ec GIT binary patch literal 822 zcmd6i&r1S96vw~OjLI$aCb=#Fjw*hyi)2>D*apF9=K6*2R!`xm%ur2szeGS zN{_<)NIn4+$g~Se5C5fq7XDOmyj*SWkHs8a9}6)~r$-8exJsq2<8d#Ma7}YkDoqQ8 ziGpJBF`u6@<}v10Do>U*uhpIvSk|msec{~W+-)?LjGetHeight(); 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 6af8c86ba885e504efbfbef1310710774856689b..96d313d758e43af500dd7d848043e3d0b24c4c32 100644 GIT binary patch delta 4150 zcmeHKZEO@p7@nP*z1!Q{D@SRsy;A8xL5 zTdrt;U~HLBQFnO2FceueHhpExlon#gH^y9P z4YWN+q^^%C<*|99==2WygW-75cyO2LiR8&|4Xspu=#IA&H5^P=D1$pz0^ZlHY`7u(F+{7-nm zY2G%s@)(cKNzcJII(V8Reg$+TAeg3k;qLqHY#8j}mmg_Q1OEqZKU_P?3sUX4rP-u5}x2oXMK7OPQ_%Y#)UX1qO;b&~snUMdx%Y$P}ZPy#RFZSDVK)fP6*mA<2 zq2M1EY=;V^^GiaWEq#;L(nXT4yaq_DS$Nwc#-(o_NwM&!i@?w5Z75h-h4@o*&r5FHzjoUWxJN6;P75!M1htX;em^{ok0xMs0%(b zb+~d|U6q~CA&?FSaFx?u)R)p>Po+$OPp$O-Z>6KT7^xGx3LtE_$5Q%)LvD8^zSiuB zy_ssmQz!InC$z`(S!P@7eTP@E`PnXLyYI+U{j8Slfc5>3OlU-1!(ZC?b|tQB3_o!6 zD6oRt7C?0;UkWWZgbu@{Y6i?YqkEurvE9JzMt7}>ovK!-CD(#!%7ZYRrmcLWJz>hv z#@lt+K1~alo#e~`9G#}^OxSZSG^cBcwR063=efSa`V1{UKU&&e3!Wiy0Gc;D>@Ysv znT@9_v@&OEl^j2KwnoFVHO|vrPnXAkg4UCiG?0?Us&tH0=^xom@fU8;_fLu$w_T|zZ=EX?LG zH`7y3uVWz^FbHpN;j@Y4qvNceYMhBmCdUmC*^QLo*Tj+Y9uGNHYl&S+=r7AT7f;1G z#1fSjxYaZh#5meC(+80)Tzfp$6V>#h)(fX%JyDs&g|(IHY|Oc!FPiYd z$R#}=DMO4NF_S_4TdqA>rsn~9UIaWvhQNY|tNL6jBkbW2{*;_Ha?(Y~`I2pef{lZA z%@5-zRXdy#E-&`h8FvFut@6pV%HT@V87V&OoaBuDuzSU%53v1v-4h>RlnMe4s~!Jd b(mWF(AhFq}GO~d977w(=m!h}X?Xmp>0o*I$ delta 2477 zcmds&Urbw79LIZ3&+R?Ey|<%H2ed*h23;k{%AeI_K{8(u5rJXF#Tdmu55_pGi4P>= z(#7cJmP{ktehC^jy9sU)R<^7^Cxp~xA0i3HY$=fiND7n#HN7?Y);uR+sq5 z+d04U`<;94`Fy{>voanYj)xO%48kgRI$p9oXL-`nZmGA_!FR1v#lY(<4CxW-+_crQ z)snxuG|$dM&ls&7=;7-7dnDW=5#_2Bvh-PMar{fQg6QKP=ZIv}$F-Vl#%sq^S&zfp zCCrQMi$pbwb}y0pjH2-g^+7!jn*t(n`6i*pBDqD3MeMkwt`$|uX8hRiYn%OW$IOSv z!(uc4-{xlURwMI*I7TzfG_q;^%zGEqQ58Z5)xm-2qj8LQXz+e;f2x&1=Vr|bvqvb$ zuj}cbFRukr1Vi?`dGHub(%d|7iZYlzNm(*ZZ8AhOUN$0PBs&5za>I@jvI;eE*#;pO zcf!yq%Hf^Uw8l(fm^w`l(7Pjp{iD=5(8oNPL9j496!0c{p=g_03ZYf$D_khIc5Q~0 z4;)i?v)&qd4~xgG)Q7Q7^&x_dSFQUSb2kElZV9e%rWmyH5Q9Km0+WxhW{4HBOL~Q1 zU4p$XwkqkDDu5e!K(O}aDn2P^3}=_fH+mWf^j=)`GgB9WzkwJ8dcCga7SU;e(0~^Y zZDEE$V7yB9qBxJS1qd}{%UY6ukZ+9-30dfSO*JqM(QRx>KdBIj@kJE+Fi$OH;l$7$~*Ta1TCwEFO4rR50LK`uRA{Ta^Pzhl(GB{A=J~NdYQ>qJLJbq1SxEID~tI9BOj`;}0`W-%8Oe+gVb3UKl?Ff`+upYjWvAF-) zjmhx*_Usj-K#)%Z#O=4?jy`Rfo5-9P*{iL8xBs_SKZn?1t;zJ|I>Wj%t4>I5(S*-k PJZR?W{vAA`MXdh-=