Use a better look for the separator in RAM watch.
There are still many disadvantages, the list is not efficient enough since the separator needs too much calculation, when there are too many separators, the watchlist maybe slow. I think some of their data can be stored in some map or list for fast accessing in the future development, since they don't requires calc every time.
This commit is contained in:
parent
a9a027940b
commit
993b6fbb2c
|
@ -14,6 +14,18 @@ static int mapInputSortCol = -1;
|
|||
// whether it's asc or desc sorting, when sortCol is -1, this value has no effect
|
||||
static bool mapInputSortAsc = true;
|
||||
|
||||
// an ugly macro function
|
||||
#define UpdateListViewSort(hwndListView, lpListView, filter) \
|
||||
if (filter == EMUCMDTYPE_MAX + 3) \
|
||||
lpListView->iSubItem = 2; \
|
||||
else if (filter > EMUCMDTYPE_MISC && filter < EMUCMDTYPE_MAX || filter == EMUCMDTYPE_MAX + 2) \
|
||||
lpListView->iSubItem = 1; \
|
||||
else \
|
||||
lpListView->iSubItem = mapInputSortCol; \
|
||||
if (SendMessage(hwndListView, LVM_SORTITEMS, (WPARAM)lpListView, (LPARAM)MapInputItemSortFunc)) \
|
||||
UpdateSortColumnIcon(hwndListView, mapInputSortCol, mapInputSortAsc);
|
||||
|
||||
|
||||
void KeyboardUpdateState(void); //mbg merge 7/17/06 yech had to add this
|
||||
|
||||
struct INPUTDLGTHREADARGS
|
||||
|
@ -564,22 +576,12 @@ void PopulateMappingDisplay(HWND hwndDlg)
|
|||
hdr.hwndFrom = hwndListView;
|
||||
hdr.code = LVN_COLUMNCLICK;
|
||||
|
||||
NMLISTVIEW listView;
|
||||
listView.hdr = hdr;
|
||||
NMLISTVIEW* lpListView = new NMLISTVIEW;
|
||||
lpListView->hdr = hdr;
|
||||
|
||||
// when showing the conflict table, always sorted by "Input" column first,
|
||||
// So the user can easily find out which are conflicting.
|
||||
if (filter == EMUCMDTYPE_MAX + 3)
|
||||
listView.iSubItem = 2;
|
||||
// only one type is in the list, just sort with "Command" column
|
||||
// "Unassigned" has no text in "Input", just sort with "Command" column
|
||||
else if (filter > EMUCMDTYPE_MISC && filter < EMUCMDTYPE_MAX || filter == EMUCMDTYPE_MAX + 2)
|
||||
listView.iSubItem = 1;
|
||||
else
|
||||
listView.iSubItem = mapInputSortCol;
|
||||
UpdateListViewSort(hwndListView, lpListView, filter);
|
||||
|
||||
int ret = SendMessage(hwndListView, LVM_SORTITEMS, (WPARAM)&listView, (LPARAM)MapInputItemSortFunc);
|
||||
UpdateSortColumnIcon(hwndListView, mapInputSortCol, mapInputSortAsc);
|
||||
delete lpListView;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -792,27 +794,14 @@ BOOL CALLBACK MapInputDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM
|
|||
case LVN_COLUMNCLICK:
|
||||
// Sort the items
|
||||
if (mapInputSortCol != lpListView->iSubItem) {
|
||||
mapInputSortCol= lpListView->iSubItem;
|
||||
mapInputSortCol = lpListView->iSubItem;
|
||||
mapInputSortAsc = true;
|
||||
}
|
||||
else
|
||||
mapInputSortAsc = !mapInputSortAsc;
|
||||
|
||||
int filter = (int)SendDlgItemMessage(hwndDlg, COMBO_FILTER, CB_GETCURSEL, 0, 0);
|
||||
|
||||
// when showing the conflict table, always sorted by "Input" column first,
|
||||
// So the user can easily find out which are conflicting.
|
||||
if (filter == EMUCMDTYPE_MAX + 3)
|
||||
lpListView->iSubItem = 2;
|
||||
// only one type is in the list, just sort with "Command" column
|
||||
// "Unassigned" has no text in "Input", just sort with "Command" column
|
||||
else if (filter > EMUCMDTYPE_MISC && filter < EMUCMDTYPE_MAX || filter == EMUCMDTYPE_MAX + 2)
|
||||
lpListView->iSubItem = 1;
|
||||
else
|
||||
lpListView->iSubItem = mapInputSortCol;
|
||||
|
||||
int ret = SendMessage(hwndListView, LVM_SORTITEMS, (WPARAM)lpListView, (LPARAM)MapInputItemSortFunc);
|
||||
UpdateSortColumnIcon(hwndListView, mapInputSortCol, mapInputSortAsc);
|
||||
UpdateListViewSort(hwndListView, lpListView, filter);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -204,16 +204,19 @@ void Update_RAM_Watch()
|
|||
// update cached values and detect changes to displayed listview items
|
||||
|
||||
for(int i = 0; i < WatchCount; i++)
|
||||
{
|
||||
if (rswatches[i].Type != 'S')
|
||||
{
|
||||
unsigned int prevCurValue = rswatches[i].CurValue;
|
||||
unsigned int newCurValue = GetCurrentValue(rswatches[i]);
|
||||
if(prevCurValue != newCurValue)
|
||||
if (prevCurValue != newCurValue)
|
||||
{
|
||||
rswatches[i].CurValue = newCurValue;
|
||||
watchChanged[i] = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// refresh any visible parts of the listview box that changed
|
||||
HWND lv = GetDlgItem(RamWatchHWnd,IDC_WATCHLIST);
|
||||
|
@ -918,10 +921,9 @@ void RefreshWatchListSelectedCountControlStatus(HWND hDlg)
|
|||
|
||||
LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
RECT r;
|
||||
RECT r2;
|
||||
int dx1, dy1, dx2, dy2;
|
||||
static int watchIndex=0;
|
||||
static int watchIndex = 0; // current watch index
|
||||
static HPEN sepPen, sepPenSel; // separator line colors
|
||||
static HFONT sepFon; // separator fonts
|
||||
|
||||
switch(uMsg)
|
||||
{
|
||||
|
@ -941,6 +943,9 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
|
|||
} break;
|
||||
|
||||
case WM_INITDIALOG: {
|
||||
RECT r, r2;
|
||||
int dx1, dy1, dx2, dy2;
|
||||
|
||||
GetWindowRect(hWnd, &r); //Ramwatch window
|
||||
dx1 = (r.right - r.left) / 2;
|
||||
dy1 = (r.bottom - r.top) / 2;
|
||||
|
@ -984,7 +989,7 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
|
|||
UpdateRW_RMenu(rwrecentmenu, RAMMENU_FILE_RECENT, RW_MENU_FIRST_RECENT_FILE);
|
||||
|
||||
const char* names[3] = {"Address","Value","Notes"};
|
||||
int widths[3] = {62,64,64+51+53};
|
||||
int widths[3] = {68,64,64+51+53};
|
||||
init_list_box(GetDlgItem(hDlg,IDC_WATCHLIST),names,3,widths);
|
||||
if (!ResultCount)
|
||||
reset_address_info();
|
||||
|
@ -1004,6 +1009,14 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
|
|||
DragAcceptFiles(hDlg, TRUE);
|
||||
|
||||
RefreshWatchListSelectedCountControlStatus(hDlg);
|
||||
|
||||
sepPen = CreatePen(PS_SOLID, 1, RGB(160, 160, 160));
|
||||
sepPenSel = CreatePen(PS_SOLID, 1, RGB(224, 224, 224));
|
||||
LOGFONT logFont;
|
||||
GetObject((HANDLE)SendDlgItemMessage(hDlg, IDC_WATCHLIST, WM_GETFONT, NULL, NULL), sizeof(logFont), &logFont);
|
||||
logFont.lfWeight = FW_SEMIBOLD;
|
||||
sepFon = (HFONT)CreateFontIndirect(&logFont);
|
||||
|
||||
return false;
|
||||
} break;
|
||||
|
||||
|
@ -1032,7 +1045,7 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
|
|||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
case IDC_WATCHLIST:
|
||||
{
|
||||
LPNMHDR lP = (LPNMHDR) lParam;
|
||||
switch (lP->code)
|
||||
|
@ -1051,45 +1064,45 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
|
|||
case LVN_GETDISPINFO:
|
||||
{
|
||||
LV_DISPINFO *Item = (LV_DISPINFO *)lParam;
|
||||
Item->item.mask = LVIF_TEXT;
|
||||
Item->item.state = 0;
|
||||
Item->item.iImage = 0;
|
||||
const unsigned int iNum = Item->item.iItem;
|
||||
if (rswatches[iNum].Type != 'S')
|
||||
{
|
||||
Item->item.mask = LVIF_TEXT;
|
||||
static char num[11];
|
||||
switch (Item->item.iSubItem)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
case 0: {
|
||||
int size = WatchSizeConv(rswatches[iNum]);
|
||||
int addr = rswatches[iNum].Address;
|
||||
sprintf(num, rswatches[iNum].Type == 'S' ? "------" : size > 1 ? "%04X-%04X" : "%04X", addr, addr + size - 1);
|
||||
sprintf(num, size > 1 ? "%04X-%04X" : "%04X", addr, addr + size - 1);
|
||||
Item->item.pszText = num;
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
int i = rswatches[iNum].CurValue;
|
||||
int t = rswatches[iNum].Type;
|
||||
int size = rswatches[iNum].Size;
|
||||
const char* formatString = ((t=='s') ? "%d" : (t=='u') ? "%u" : (size=='d' ? "%08X" : size=='w' ? "%04X" : "%02X"));
|
||||
const char* formatString = ((t == 's') ? "%d" : (t == 'u') ? "%u" : (size == 'd' ? "%08X" : size == 'w' ? "%04X" : "%02X"));
|
||||
switch (size)
|
||||
{
|
||||
case 'b':
|
||||
default: sprintf(num, formatString, t=='s' ? (char)(i&0xff) : (unsigned char)(i&0xff)); break;
|
||||
case 'w': sprintf(num, formatString, t=='s' ? (short)(i&0xffff) : (unsigned short)(i&0xffff)); break;
|
||||
case 'd': sprintf(num, formatString, t=='s' ? (long)(i&0xffffffff) : (unsigned long)(i&0xffffffff)); break;
|
||||
case 'S': sprintf(num, "---------"); break;
|
||||
default: sprintf(num, formatString, t == 's' ? (char)(i & 0xff) : (unsigned char)(i & 0xff)); break;
|
||||
case 'w': sprintf(num, formatString, t == 's' ? (short)(i & 0xffff) : (unsigned short)(i & 0xffff)); break;
|
||||
case 'd': sprintf(num, formatString, t == 's' ? (long)(i & 0xffffffff) : (unsigned long)(i & 0xffffffff)); break;
|
||||
}
|
||||
|
||||
Item->item.pszText = num;
|
||||
} return true;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
Item->item.pszText = rswatches[iNum].comment ? rswatches[iNum].comment : (char*)"";
|
||||
return true;
|
||||
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case LVN_ODFINDITEM:
|
||||
{
|
||||
// disable search by keyboard typing,
|
||||
|
@ -1100,15 +1113,57 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
|
|||
}
|
||||
case NM_CUSTOMDRAW:
|
||||
{
|
||||
LPNMCUSTOMDRAW nmcd = (LPNMCUSTOMDRAW)lParam;
|
||||
NMCUSTOMDRAW* nmcd = (NMCUSTOMDRAW*)lParam;
|
||||
switch (nmcd->dwDrawStage)
|
||||
{
|
||||
case CDDS_ITEMPREPAINT:
|
||||
{
|
||||
LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;
|
||||
case CDDS_ITEMPOSTPAINT:
|
||||
// Here is the separator actually drawn
|
||||
if (rswatches[nmcd->dwItemSpec].Type == 'S')
|
||||
lplvcd->clrTextBk = RGB(247, 187, 67);
|
||||
{
|
||||
char* comment = rswatches[nmcd->dwItemSpec].comment;
|
||||
RECT rect;
|
||||
rect.left = LVIR_BOUNDS;
|
||||
SendDlgItemMessage(hDlg, IDC_WATCHLIST, LVM_GETITEMRECT, nmcd->dwItemSpec, (LPARAM)&rect);
|
||||
HDC hdc = nmcd->hdc;
|
||||
|
||||
// This value is required, when you click outside any items in the list there's nothing selected, but the frame is still on the separator, it would draw with the wrong color. I don't know if there's a better way to check this state, since nmcd->uItemState doesn't seem tohave a value for it.
|
||||
// int selCount = SendDlgItemMessage(hDlg, IDC_WATCHLIST, LVM_GETSELECTEDCOUNT, 0, 0);
|
||||
int state = SendDlgItemMessage(hDlg, IDC_WATCHLIST, LVM_GETITEMSTATE, nmcd->dwItemSpec, LVIS_SELECTED);
|
||||
|
||||
// draw the comment as the separator title
|
||||
if (comment != NULL && strcmp(comment, ""))
|
||||
{
|
||||
SIZE size;
|
||||
SelectObject(hdc, sepFon);
|
||||
GetTextExtentPoint(hdc, comment, strlen(comment), &size);
|
||||
int adjust = (rect.bottom - rect.top - size.cy) / 2;
|
||||
rect.bottom -= adjust;
|
||||
rect.top += adjust;
|
||||
int right = rect.right;
|
||||
rect.right = (rect.left += 6) + size.cx;
|
||||
// draw it with a different color when hilighted for eyes easy
|
||||
SetTextColor(hdc, state ? RGB(229, 224, 236) : RGB(43, 145, 175));
|
||||
DrawText(hdc, comment, strlen(comment), &rect, DT_VCENTER);
|
||||
rect.left = rect.right;
|
||||
rect.right = right;
|
||||
}
|
||||
|
||||
// draw the separator
|
||||
// draw it with a different color when hilighted for eyes easy
|
||||
SelectObject(hdc, state ? sepPenSel : sepPen);
|
||||
int posy = (rect.bottom - rect.top) / 2 + rect.top;
|
||||
// Is there a way to find real ident of the highlight mark in the first cloumn?
|
||||
MoveToEx(hdc, rect.left += 4, posy, NULL);
|
||||
LineTo(hdc, rect.right, posy);
|
||||
}
|
||||
break;
|
||||
case CDDS_ITEMPREPAINT:
|
||||
if (rswatches[nmcd->dwItemSpec].Type == 'S')
|
||||
// A separator looks very different from normal watches, it should be drawn in another space while I want to use the highlight bar and the focus frame from the system.
|
||||
SetWindowLong(hDlg, DWL_MSGRESULT, CDRF_NOTIFYPOSTPAINT);
|
||||
else
|
||||
{
|
||||
NMLVCUSTOMDRAW* lplvcd = (NMLVCUSTOMDRAW*)lParam;
|
||||
switch (rswatches[nmcd->dwItemSpec].Cheats)
|
||||
{
|
||||
default:
|
||||
|
@ -1133,12 +1188,11 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
|
|||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
}
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
switch(LOWORD(wParam))
|
||||
{
|
||||
|
@ -1349,6 +1403,11 @@ LRESULT CALLBACK RamWatchProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
|
|||
RamWatchHWnd = NULL;
|
||||
DragAcceptFiles(hDlg, FALSE);
|
||||
WriteRecentRWFiles(); // write recent menu to ini
|
||||
|
||||
DeleteObject(sepFon);
|
||||
DeleteObject(sepPen);
|
||||
DeleteObject(sepPenSel); // delete drawing objects;
|
||||
|
||||
break;
|
||||
|
||||
case WM_DROPFILES:
|
||||
|
|
Loading…
Reference in New Issue