Files
BeneficialCode-WinArk/WinArk/Table.h
T

1833 lines
56 KiB
C++

#pragma once
#include <string>
#include <algorithm>
#include <atlstr.h>
#include <vector>
#include <memory>
#include "SortHelper.h"
#include "Helpers.h"
constexpr int NBAR = 30;
typedef unsigned char uchar; // Unsigned character (byte)
typedef unsigned short ushort; // Unsigned short
typedef unsigned int uint; // Unsigned integer
typedef unsigned long ulong; // Unsigned long
#define BAR_PRESSED 0x01 // Bar segment pressed, used internally
#define BAR_DISABLED 0x02 // Bar segment disabled
#define BAR_NOSORT 0x04 // Flat bar column, supports no sorting
#define BAR_NORESIZE 0x08 // Bar column cannot be resized
#define BAR_BUTTON 0x10 // Segment sends WM_USER_BAR
#define BAR_SHIFTSEL 0x20 // Selection shifted 1/2 char to left
#define CAPT_FREE 0 // Bar and data are not captured
#define CAPT_SPLIT 0x1
#define CAPT_BAR 0x2
#define CAPT_DATA 0x3
#define DRAW_NORMAL 0x0000 // Normal plain text
#define DRAW_GRAY 0x0001 // Grayed text
#define DRAW_HILITE 0x0002 // 绘制高亮文本
#define DRAW_UL 0x0004 // Underlined text
#define DRAW_SELECT 0x0008 // 绘制选中背景色
#define DRAW_EIP 0x0010 // Inverted normal text/background
#define DRAW_BREAK 0x0020 // 绘制断点背景色
#define DRAW_GRAPH 0x0040 // Graphical element
#define DRAW_DIRECT 0x0080 // Direct text colour index (mask only)
#define DRAW_MASK 0x0080 // Use mask to set individual colors
#define DRAW_EXTSEL 0x0100 // Extend mask till end of column
#define DRAW_UNICODE 0x0200 // Text in UNICODE
#define DRAW_TOP 0x0400 // 绘制文本上半截
#define DRAW_BOTTOM 0x0800 // 绘制文本下半截
#define TABLE_DIR 0x0001 // Bottom-to-top table
#define TABLE_COPYMENU 0x0002 // Attach copy item
#define TABLE_SORTMENU 0x0004 // Attach sort menu
#define TABLE_APPMENU 0x0010 // Attach appearance menu
#define TABLE_WIDECOL 0x0020 // Attach wide columns menu item
#define TABLE_USERAPP 0x0040 // Attach user-processed appearance menu
#define TABLE_USERDEF 0x0080 // User-drawn table
#define TABLE_NOHSCR 0x0100 // Table contains no horizontal scroll
#define TABLE_SAVEPOS 0x0200 // Save position & appearance to .ini
#define TABLE_CPU 0x0400 // Table belongs to CPU window
#define TABLE_FASTSEL 0x0800 // Update when selection changes
#define TABLE_COLSEL 0x1000 // Column-wide selection
#define TABLE_SAVEAPP 0x2000 // Save multiinstance appearance to .ini
#define TABLE_HILMENU 0x4000 // Attach Syntax highlighting menu
#define TABLE_ONTOP 0x8000 // Attach Always on top menu
// Symbolic names for graphical characters. Any other character is displayed
// as space. Use only characters in range [1..0x7F]!
#define D_SPACE 'N' // Space
#define D_SEP ' ' // 分割线
#define D_BEGIN 'B' // 函数头
#define D_BODY 'I' // 函数体
#define D_ENTRY 'J' // Loop entry point
#define D_LEAF 'K' // Intermediate leaf on a tree
#define D_END 'E' // 函数尾
#define D_SINGLE 'S' // Single-line scope
#define D_ENDBEG 'T' // End and begin of stack scope
#define D_POINT '.' // Point
#define D_JMPUP 'U' // Jump upstairs
#define D_JMPOUT '<' // 跳转到模块外,或者同一个地方
#define D_JMPDN 'D' // 向下跳转
#define D_PATHUP 'u' // Jump path upstairs (highlighted)
#define D_GRAYUP 'v' // Jump path upstairs (grayed)
#define D_PATH 'i' // Jump path through text (highlighted)
#define D_GRAYPATH 'j' // Jump path through text (grayed)
#define D_PATHDN 'd' // Jump path downstairs (highlighted)
#define D_GRAYDN 'e' // Jump path downstairs (grayed)
#define D_PATHUPEND 'r' // End of path upstairs (highlighted)
#define D_GRAYUPEND 's' // End of path upstairs (grayed)
#define D_PATHDNEND 'f' // End of path downstairs (highlighted)
#define D_GRAYDNEND 'g' // End of path downstairs (grayed)
#define D_SWTOP 't' // switch 开始
#define D_SWBODY 'b' // switch 体
#define D_CASE 'c' // Intermediate switch case
#define D_LASTCASE 'l' // Last switch case
#define WM_USER_MENU (WM_USER+101) // 激活上下文菜单 // 0x465
#define WM_USER_SCR (WM_USER+102) // Redraw scroll(s) 0x466
#define WM_USER_SAVE (WM_USER+103) // Save data to disk 0x467
#define WM_USER_VABS (WM_USER+104) // Scroll contents of window by lines 0x468
#define WM_USER_VREL (WM_USER+105) // Scroll contents of window by percent 0x469
#define WM_USER_VBYTE (WM_USER+106) // Scroll contents of window by bytes 0x46a
#define WM_USER_STS (WM_USER+107) // Start selection in window 0x46b
#define WM_USER_CNTS (WM_USER+108) // Continue selection in window 0x46c
#define WM_USER_CHGS (WM_USER+109) // 移动单行选择 0x46d
#define WM_USER_BAR (WM_USER+110) // Message from bar segment as button 0x46e
#define WM_USER_DBLCLK (WM_USER+111) // Doubleclick in column 0x46f
#define WM_USER_SIZE (WM_USER+112) // Resize children in CPU window 0x470
#define WM_USER_FOCUS (WM_USER+113) // Set focus to child of CPU window 0x471
#define WM_USER_FILE (WM_USER+114) // Change state of file dump 0x472
#define WM_USER_HERE (WM_USER+115) // Query presence list 0x473
#define WM_USER_CHALL (WM_USER+116) // Redraw (almost) everything 0x474
#define WM_USER_CHMEM (WM_USER+117) // Range of debuggee's memory changed 0x475
#define WM_USER_CHREG (WM_USER+118) // Debuggee's register(s) changed // 0x476
#define WM_USER_CHNAM (WM_USER+119) // Redraw name tables // 0x477
#define WM_USER_MOUSE (WM_USER+120) // Check mouse coordinates // 0x478
#define WM_USER_KEY (WM_USER+121) // Emulate WM_KEYDOWN // 0x479
#define WM_USER_SYSKEY (WM_USER+122) // Emulate WM_SYSKEYDOWN // 0x47A
struct t_bar {
int nbar; // 列数
int font; // 字体
int dx[NBAR]; // 实际宽度
int defdx[NBAR]; // 默认宽度
std::string name[NBAR]; // 名字
uchar mode[NBAR]; // 模式
int captured; // 是否被捕获
int active; // 鼠标捕获的哪一列
int prevx; // 鼠标之前的坐标
};
struct BarDesc {
int defdx;
std::string name;
uchar mode;
};
struct BarInfo {
BarDesc bar[NBAR];
int font;
int nbar;
int captured;
};
struct TableInfo {
int showbar;
int hscroll;
int mode;
int font;
int scheme;
int offset;
int xshift;
};
template<typename T>
struct t_sorted {
std::string name; // 表名
int n{0}; // 实际项数
int nmax; // 最大项数
int selected; // 选中索引
ulong seladdr; // 选中的基地址
bool sorted; // 索引是否被排序
int sort; // 被排序的列
int version{ 0 }; // 版本
std::vector<int> index[NBAR]; // 索引
bool AutoSort{ false }; // 是否可以自动排序
std::vector<T> info;
};
template<typename T>
struct t_table {
HWND hw; // 窗口句柄
t_sorted<T> data; // 数据
int showbar; // 显示,隐藏,缺省
short hscroll; // 水平滚动条,显示,隐藏
short colsel; // 选中表格第二项
int mode; // 模式
int font; // 字体
short scheme; // 色彩主题
short hilite; // 高亮主题
int offset; // 显示首行位置
int xshift; // 位置移动
};
struct t_process {
DWORD pid;
CString ProcessName;
CString Path;
};
template<class T>
class CTable {
public:
CTable(BarInfo& bars,TableInfo& table);
void Defaultbar();
void PaintBar(HDC hdc, LPRECT rect, int iColumn);
void PaintTable(HWND hw);
int Tablefunction(HWND hw, UINT msg, WPARAM wp, LPARAM lp);
virtual int GetRowImage(HWND, int row) const {
return -1;
}
bool Sortsorteddata(int sort);
virtual bool CompareItems(const T& i1, const T& i2, int col,bool asc=true) {
return false;
}
T Getsortedbyselection(int row);
template<class T>
static DWORD GetSeladdr(const T& t) {
return 0;
}
template<>
static DWORD GetSeladdr(const t_process& t) {
return t.pid;
}
static void Addsorteddata(const T& t);
static void Deletesorteddata(ulong addr);
virtual int ParseTableEntry(CString& s, char& mask, int& select, T& info, int column) {
return 0;
}
void GetSysKeyState(UINT msg, LPARAM lp, bool& pressShift, bool& pressCtrl);
void SetTableWindowInfo(int maxColumns,int nlines = 20);
public:
t_bar m_Bar;
static RECT m_Rect;
static DWORD _style;
static t_table<T> m_Table;
bool m_bSnowFreeDrawing{ true }; // 是否内存绘图
bool m_bHighlightSortedColumn{ false };
int m_BkColorIndex[8] = { -1,0,7,15,11,10,12,14 };
int _row;
int _page{ 0 };
mutable CImageList m_Images;
};
template <class T>
DWORD CTable<T>::_style = 0;
template <class T>
RECT CTable<T>::m_Rect = { 0 };
template <class T>
t_table<T> CTable<T>::m_Table;
template<class T>
T CTable<T>::Getsortedbyselection(int row) {
return m_Table.data.info[row];
}
template<class T>
void CTable<T>::GetSysKeyState(UINT msg, LPARAM lp, bool& pressShift, bool& pressCtrl) {
if (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) {
pressShift = GetKeyState(VK_SHIFT) & 0x8000;
pressCtrl = GetKeyState(VK_CONTROL) & 0x8000;
}
else {
pressShift = LOWORD(lp);
pressCtrl = HIWORD(lp);
}
}
template<class T>
CTable<T>::CTable(BarInfo& bars,TableInfo& table) {
ATLASSERT(bars.nbar < NBAR&& bars.nbar>0);
ATLASSERT(bars.font > 0 && bars.font < 11);
m_Table.showbar = table.showbar;
m_Table.hscroll = table.hscroll;
m_Table.mode = table.mode;
m_Table.font = table.font;
m_Table.scheme = table.scheme;
m_Table.offset = table.offset;
m_Table.xshift = table.xshift;
m_Bar.font = bars.font;
m_Bar.nbar = bars.nbar;
m_Bar.captured = bars.captured;
for (int i = 0; i < bars.nbar; i++) {
m_Bar.defdx[i] = bars.bar[i].defdx;
m_Bar.name[i] = bars.bar[i].name;
m_Bar.mode[i] = bars.bar[i].mode;
}
Defaultbar();
}
template<class T>
void CTable<T>::Defaultbar() {
int i = 0;
while (i < m_Bar.nbar) {
m_Bar.dx[i] = g_AvWidthFont * m_Bar.defdx[i];
++i;
}
}
template<class T>
void CTable<T>::PaintBar(HDC hdc, LPRECT client, int iColumn) {
ATLASSERT(hdc && client);
int font;
RECT bar, col;
if (client->left < client->right && client->top < client->bottom) {
font = m_Bar.font;
SetTextAlign(hdc, TA_LEFT | TA_BOTTOM);
SetBkColor(hdc, g_crLightGray);
SelectObject(hdc, g_hOemFixedFont);
memcpy(&bar, client, sizeof(bar));
client->top += g_AvHighFont + 4;
bar.bottom = client->top - 1;
SelectObject(hdc, g_hBlackPen);
MoveToEx(hdc, bar.left, bar.bottom, NULL);
LineTo(hdc, bar.right, bar.bottom); // 画出列标题的框
int i = 0;
while (m_Bar.nbar > i) {
if (m_Bar.dx[i] > 0) {
if (client->right <= bar.left)
break;
memcpy(&col, &bar, sizeof(col));
bar.left = col.left + m_Bar.dx[i];
col.right = bar.left - 1;
SelectObject(hdc, g_hBlackPen);
MoveToEx(hdc, col.right, col.top, NULL);
LineTo(hdc, col.right, col.bottom); // 右边界为黑色
int x = col.left + g_AvWidthFont / 2;
int y = col.bottom - 1;
// 设置边框分格
if (m_Bar.mode[i] & BAR_NOSORT) { // 不可排序上边界为白线
SelectObject(hdc, g_hWhitePen);
MoveToEx(hdc, col.left, col.top, NULL);
LineTo(hdc, col.right, col.top);
++col.top;
}
else if ((m_Bar.mode[i] & BAR_PRESSED) == BAR_PRESSED) { // 按压时,左边界和上边界为黑灰色
SelectObject(hdc, g_hDarkGrayPen);
MoveToEx(hdc, col.left, col.bottom - 1, NULL);
LineTo(hdc, col.left, col.top);
LineTo(hdc, col.right, col.top);
++col.left;
++col.top;
++x;
++y;
}
else {
--col.bottom;
SelectObject(hdc, g_hWhitePen); // 左边界为白色
MoveToEx(hdc, col.left, col.bottom, NULL);
LineTo(hdc, col.left, col.top);
LineTo(hdc, col.right, col.top);
++col.left;
--col.right;
SelectObject(hdc, g_hDarkGrayPen); // 右边界为黑灰色
MoveToEx(hdc, col.left, col.bottom, NULL);
LineTo(hdc, col.right, col.bottom);
LineTo(hdc, col.right, col.top);
++col.top;
}
// 设置字体颜色和背景颜色
if (m_Bar.mode[i] & BAR_DISABLED) {
SetTextColor(hdc, g_crDarkGray);
SetBkColor(hdc, g_crLightGray);
}
else if (m_Bar.mode[i] & BAR_NOSORT || !m_bHighlightSortedColumn || i != iColumn) {
SetTextColor(hdc, g_crBlack);
SetBkColor(hdc, g_crLightGray);
}
else {
SetTextColor(hdc, g_crBlack);
SetBkColor(hdc, g_myColor[18]);
}
// 输出列标题 column captions
int len = 0;
len = m_Bar.name[i].length();
ExtTextOutA(hdc, x, y, ETO_CLIPPED | ETO_OPAQUE, &col, m_Bar.name[i].c_str(), len, NULL);
}
i++;
}
if (bar.left < bar.right) { // 未定义区域的上边界为白色
SelectObject(hdc, g_hWhitePen);
MoveToEx(hdc, bar.left, bar.top, NULL);
LineTo(hdc, bar.right, bar.top);
++bar.top;
FillRect(hdc, &bar, g_hLightGrayBrush);
}
}
}
template<class T>
bool CTable<T>::Sortsorteddata(int sort) {
if (m_Table.data.sorted && sort == m_Table.data.sort) {
return false;
}
std::sort(m_Table.data.info.begin(), m_Table.data.info.end(), [=](const auto& i1, const auto& i2) {
return CompareItems(i1, i2, sort);
});
m_Table.data.sort = sort;
return true;
}
template<class T>
void CTable<T>::Deletesorteddata(ulong addr) {
std::remove_if(m_Table.data.info.begin(), m_Table.data.info.end(), [=](auto& p) {
return GetSeladdr(p) == addr;
});
m_Table.data.n--;
}
template<class T>
void CTable<T>::Addsorteddata(const T& t) {
m_Table.data.info.push_back(t);
m_Table.data.n++;
}
template<class T>
void CTable<T>::PaintTable(HWND hw) {
HDC hdc, hdcMem;
PAINTSTRUCT ps;
RECT client, row, entry, txt;
int column;
int fontHeight;
HBITMAP hBitmap;
HGDIOBJ hgdiMem;
T info;
Tablefunction(hw, WM_USER_SCR, 0, 0); // 重绘滚动条
hdc = BeginPaint(hw, &ps);
GetClientRect(hw, &client);
if (m_Table.mode & TABLE_USERDEF || m_Bar.nbar > 0) {
client.left = -m_Table.xshift;
if (m_Table.showbar == 1) { // 显示
column = -1;
PaintBar(hdc, &client, column);
}
fontHeight = g_AvHighFont;
if (m_bSnowFreeDrawing) {
hdcMem = CreateCompatibleDC(hdc);
if (hdcMem) {
hBitmap = CreateCompatibleBitmap(hdc, client.right, fontHeight);
}
else {
hBitmap = NULL;
}
if (hBitmap) {
hgdiMem = SelectObject(hdcMem, hBitmap);
}
else {
hdcMem = hdc;
m_bSnowFreeDrawing = false;
}
}
else {
hdcMem = hdc;
}
SelectObject(hdcMem, g_hOemFixedFont);
SetTextAlign(hdcMem, TA_LEFT | TA_BOTTOM);
SetBkMode(hdcMem, TRANSPARENT);
if (m_Table.mode & TABLE_USERDEF) {
m_Table.data.n = (client.bottom - client.top - 1) / fontHeight + 1;
m_Table.offset = 0; // 设置显示首行
}
else {
if (m_Table.data.n <= m_Table.offset) {
m_Table.offset = m_Table.data.n - 1; // 显示最后一行
}
if (m_Table.offset < 0) {
m_Table.offset = 0;
}
}
memcpy(&row, &client, sizeof(row));
for (int i = m_Table.offset; m_Table.mode & TABLE_USERDEF || i < m_Table.data.n; ++i) { // 循环次数为表行数
if (m_Table.mode & TABLE_DIR) {
if (client.top >= client.bottom)
break;
row.top = row.bottom - fontHeight;
if (client.top > row.bottom - fontHeight)
row.top = client.top;
}
else {
if (row.top > client.bottom)
break;
row.bottom = fontHeight + row.top;
}
memcpy(&entry, &row, sizeof(entry));
if (m_bSnowFreeDrawing) {
entry.top = 0;
entry.bottom = fontHeight;
}
if (m_Table.mode & TABLE_USERDEF) {
m_Table.offset = i;
info = m_Table.data.info[i];
}
else {
info = m_Table.data.info[i];
}
int scheme = m_Table.scheme;
int iTxColor=0, iBkColor;
int col;
int index = -1;
int imageWidth = 18;
for (col = 0; col < m_Bar.nbar;) { // 循环次数为表列数
int width = m_Bar.dx[col];
if (entry.left > row.right)
break;
entry.right = entry.left + width - 1;
if (col == 0&&m_Images!=NULL) {
index = GetRowImage(hw,i);
if (index != -1) {
POINT pt;
pt.x = entry.left+5;
pt.y = entry.top;
FillRect(hdcMem, &entry, g_myBrush[Custom1]);
m_Images.Draw(hdcMem, index,pt, ILD_NORMAL);
entry.left += imageWidth+8;
}
}
if (width > 3) {
if (entry.right >= row.left) {
CString s;
char mask = 0;
int select = 0;
int symName = 0;
int len = ParseTableEntry(s, mask, select, info, col);
std::string t = Helpers::WstringToString(s.GetString());
HBRUSH hBkBrush;
if (!(m_Table.mode & TABLE_USERDEF) // 非自绘
&& i==m_Table.data.selected
&& !(select & DRAW_BREAK) // 不是断点
&& (!(m_Table.mode & TABLE_COLSEL) || m_Table.colsel == col)) { // 不是在改变表项宽度
select |= DRAW_SELECT;
}
int bottom;
if (select & DRAW_DIRECT) {
int drawMask = DRAW_NORMAL;
memcpy(&txt, &entry, sizeof(txt));
if (m_Bar.mode[col] & BAR_SHIFTSEL) {
txt.right = txt.left;
}
else {
txt.right = txt.left + g_AvWidthFont / 2;
}
int j = 0;
int k = 0;
while (j < len && txt.left < entry.right) {
if (k >= len || drawMask != mask || txt.right > entry.right) {
if (k != len || drawMask & DRAW_DIRECT || drawMask & (DRAW_UL | DRAW_SELECT)
&& !(select & DRAW_EXTSEL)) {
if (entry.right < txt.right) {
txt.right = entry.right;
}
}
else {
txt.right = entry.right;
}
if (txt.right > txt.left) {
if (drawMask & DRAW_DIRECT) {
iTxColor = drawMask & 0xf;
if (iTxColor > 20) {
iTxColor = g_myScheme[m_Table.scheme].textcolor;
}
iBkColor = m_BkColorIndex[((drawMask) >> 4) & 7];
if (iBkColor < 0) {
if (select & DRAW_EIP) {
iBkColor = g_myScheme[m_Table.scheme].textcolor;
}
else if (select & DRAW_BREAK) {
iBkColor = g_myScheme[m_Table.scheme].hitextcolor;
}
else if (select & DRAW_SELECT) {
iBkColor = g_myScheme[m_Table.scheme].selbkcolor;
}
else {
iBkColor = g_myScheme[m_Table.scheme].bkcolor;
}
}
}
else {
if (drawMask & DRAW_HILITE) {
iTxColor = g_myScheme[m_Table.scheme].hitextcolor;
}
else if ((drawMask | select) & DRAW_GRAY) {
iTxColor = g_myScheme[m_Table.scheme].lowcolor;
}
if ((drawMask | select) & DRAW_EIP) {
if (!(drawMask & DRAW_HILITE)) {
iTxColor = g_myScheme[m_Table.scheme].bkcolor;
}
iBkColor = g_myScheme[m_Table.scheme].textcolor;
}
else if ((drawMask | select) & DRAW_BREAK) {
iTxColor = g_myScheme[m_Table.scheme].textcolor;
iBkColor = g_myScheme[m_Table.scheme].hitextcolor;
}
else if ((drawMask ^ select) & DRAW_SELECT) {
iBkColor = g_myScheme[m_Table.scheme].selbkcolor;
}
else {
iBkColor = g_myScheme[m_Table.scheme].bkcolor;
}
}
SetTextColor(hdcMem, g_myColor[iTxColor]);
SetBkColor(hdcMem, g_myColor[iBkColor]);
bottom = entry.bottom;
if (select & DRAW_TOP) {
txt.bottom -= fontHeight / 2;
if (select & DRAW_SELECT) {
hBkBrush = g_myBrush[g_myScheme[m_Table.scheme].selbkcolor];
}
else {
hBkBrush = g_myBrush[g_myScheme[m_Table.scheme].bkcolor];
}
FillRect(hdcMem, &txt, hBkBrush);
txt.top += fontHeight / 2;
txt.bottom += fontHeight / 2;
bottom += fontHeight / 2;
}
else if (select & DRAW_BOTTOM) {
txt.bottom -= fontHeight / 2;
bottom -= fontHeight - fontHeight / 2;
}
if (select & DRAW_UNICODE) {
ExtTextOutW(hdcMem, entry.left + g_AvWidthFont / 2, bottom, ETO_CLIPPED | ETO_OPAQUE,
&txt, s.GetString(), len, NULL);
}
else {
ExtTextOutA(hdcMem, entry.left + g_AvWidthFont / 2, bottom, ETO_CLIPPED | ETO_OPAQUE,
&txt, t.c_str(), len, NULL);
}
if (drawMask & DRAW_UL) {
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].lowcolor]);
MoveToEx(hdcMem, txt.left, bottom - 1, NULL);
LineTo(hdcMem, txt.right, bottom - 1);
}
if (select & DRAW_TOP) {
txt.top -= fontHeight / 2;
}
else if (select & DRAW_BOTTOM) {
txt.bottom += fontHeight / 2;
txt.top += fontHeight;
if (select & DRAW_SELECT) {
hBkBrush = g_myBrush[g_myScheme[m_Table.scheme].selbkcolor];
}
else {
hBkBrush = g_myBrush[g_myScheme[m_Table.scheme].bkcolor];
}
FillRect(hdcMem, &txt, hBkBrush);
txt.top -= fontHeight / 2;
}
switch (symName) {
case D_SEP:
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].auxcolor]);
MoveToEx(hdcMem, g_AvWidthFont + txt.left - 1, txt.top, NULL);
LineTo(hdcMem, g_AvWidthFont + txt.left - 1, txt.bottom);
break;
case D_POINT:
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].textcolor]);
MoveToEx(hdcMem, txt.left, txt.top + fontHeight / 2, NULL);
LineTo(hdcMem, txt.left, txt.top + fontHeight / 2 + 2);
MoveToEx(hdcMem, txt.left + 1, txt.top + fontHeight / 2, 0);
LineTo(hdcMem, txt.left + 1, txt.top + fontHeight / 2 + 2);
break;
case D_JMPOUT:
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].textcolor]);
MoveToEx(hdcMem, txt.left, (txt.bottom + txt.top) / 2, 0);
LineTo(hdcMem, txt.left + 2 * g_AvWidthFont / 3 + 1, (txt.bottom + txt.top) / 2);
break;
case D_BEGIN:
case D_SWTOP:
if (symName == D_BEGIN) {
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].textcolor]);
}
else {
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].condbkcolor]);
}
MoveToEx(hdcMem, g_AvWidthFont + txt.left - 2, txt.top + fontHeight / 2 - 1, 0);
LineTo(hdcMem, txt.left, txt.top + fontHeight / 2 - 1);
LineTo(hdcMem, txt.left, txt.bottom);
MoveToEx(hdcMem, g_AvWidthFont + txt.left - 2, txt.top + fontHeight / 2 - 2, 0);
LineTo(hdcMem, txt.left + 1, txt.top + fontHeight / 2 - 2);
LineTo(hdcMem, txt.left + 1, txt.bottom);
break;
case D_JMPDN:
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].textcolor]);
MoveToEx(hdcMem, txt.left, txt.bottom - g_AvWidthFont / 3 - 3, 0);
LineTo(hdcMem, txt.left + g_AvWidthFont / 3, txt.bottom - 3);
LineTo(hdcMem, txt.left + 2 * (g_AvWidthFont / 3) + 1, txt.bottom - g_AvWidthFont / 3 - 4);
break;
case D_END:
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].textcolor]);
MoveToEx(hdcMem, txt.left, txt.top, 0);
LineTo(hdcMem, txt.left, txt.top + fontHeight / 2 + 1);
LineTo(hdcMem, g_AvWidthFont + txt.left - 1, txt.top + fontHeight / 2 + 1);
MoveToEx(hdcMem, txt.left + 1, txt.top, 0);
LineTo(hdcMem, txt.left + 1, txt.top + fontHeight / 2 + 2);
LineTo(hdcMem, g_AvWidthFont + txt.left - 1, txt.top + fontHeight / 2 + 2);
break;
case D_BODY:
case D_SWBODY:
if (symName == D_BODY) {
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].textcolor]);
}
else {
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].condbkcolor]);
}
MoveToEx(hdcMem, txt.left, txt.top, 0);
LineTo(hdcMem, txt.left, txt.bottom);
MoveToEx(hdcMem, txt.left + 1, txt.top, 0);
LineTo(hdcMem, txt.left + 1, txt.bottom);
break;
case D_ENTRY:
case D_CASE:
if (symName == D_ENTRY) {
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].textcolor]);
}
else {
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].condbkcolor]);
}
MoveToEx(hdcMem, txt.left, txt.top, 0);
LineTo(hdcMem, txt.left, txt.bottom);
MoveToEx(hdcMem, txt.left + 1, txt.top, 0);
LineTo(hdcMem, txt.left + 1, txt.bottom);
MoveToEx(hdcMem, txt.left + 2, txt.top + fontHeight / 2, 0);
LineTo(hdcMem, txt.left + 5, txt.top + fontHeight / 2);
MoveToEx(hdcMem, txt.left + 2, txt.top + fontHeight / 2 - 2, 0);
LineTo(hdcMem, txt.left + 2, txt.top + fontHeight / 2 + 3);
MoveToEx(hdcMem, txt.left + 3, txt.top + fontHeight / 2 - 1, 0);
LineTo(hdcMem, txt.left + 3, txt.top + fontHeight / 2 + 2);
break;
case D_LEAF:
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].textcolor]);
MoveToEx(hdcMem, txt.left, txt.top, 0);
LineTo(hdcMem, txt.left, txt.bottom);
MoveToEx(hdcMem, txt.left + 1, txt.top, 0);
LineTo(hdcMem, txt.left + 1, txt.bottom);
MoveToEx(hdcMem, txt.left + 1, txt.top + fontHeight / 2 + 1, 0);
LineTo(hdcMem, g_AvWidthFont + txt.left - 1, txt.top + fontHeight / 2 + 1);
MoveToEx(hdcMem, txt.left + 1, txt.top + fontHeight / 2 + 2, 0);
LineTo(hdcMem, g_AvWidthFont + txt.left - 1, txt.top + fontHeight / 2 + 2);
break;
case D_SINGLE:
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].textcolor]);
MoveToEx(hdcMem, g_AvWidthFont + txt.left - 2, txt.top + 1, 0);
LineTo(hdcMem, txt.left + 1, txt.top + 1);
LineTo(hdcMem, txt.left + 1, txt.bottom - 2);
LineTo(hdcMem, g_AvWidthFont + txt.left - 1, txt.bottom - 2);
MoveToEx(hdcMem, g_AvWidthFont + txt.left - 2, txt.top + 2, 0);
LineTo(hdcMem, txt.left, txt.top + 2);
LineTo(hdcMem, txt.left, txt.bottom - 3);
LineTo(hdcMem, g_AvWidthFont + txt.left - 1, txt.bottom - 3);
break;
case D_ENDBEG:
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].textcolor]);
MoveToEx(hdcMem, g_AvWidthFont + txt.left - 2, txt.bottom - 3, 0);
LineTo(hdcMem, txt.left, txt.bottom - 3);
LineTo(hdcMem, txt.left, txt.bottom);
MoveToEx(hdcMem, g_AvWidthFont + txt.left - 2, txt.bottom - 4, 0);
LineTo(hdcMem, txt.left + 1, txt.bottom - 4);
LineTo(hdcMem, txt.left + 1, txt.bottom);
MoveToEx(hdcMem, txt.left, txt.top, 0);
LineTo(hdcMem, txt.left, txt.top + 2);
LineTo(hdcMem, g_AvWidthFont + txt.left - 1, txt.top + 2);
MoveToEx(hdcMem, txt.left + 1, txt.top, 0);
LineTo(hdcMem, txt.left + 1, txt.top + 3);
LineTo(hdcMem, g_AvWidthFont + txt.left - 1, txt.top + 3);
break;
case D_JMPUP:
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].textcolor]);
MoveToEx(hdcMem, txt.left, txt.top + g_AvWidthFont / 3 + 2, 0);
LineTo(hdcMem, txt.left + g_AvWidthFont / 3, txt.top + 2);
LineTo(hdcMem, txt.left + 2 * (g_AvWidthFont / 3) + 1, txt.top + g_AvWidthFont / 3 + 3);
break;
case 'a':
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].hitextcolor]);
MoveToEx(hdcMem, txt.left + 2 * (g_AvWidthFont / 3), (txt.bottom + txt.top) / 2, 0);
LineTo(hdcMem, txt.left + 3, (txt.bottom + txt.top) / 2);
LineTo(hdcMem, txt.left + 1, (txt.bottom + txt.top) / 2 - 2);
LineTo(hdcMem, txt.left + 1, txt.top - 1);
MoveToEx(hdcMem, txt.left + 1, txt.bottom - 1, 0);
LineTo(hdcMem, txt.left + 1, (txt.bottom + txt.top) / 2 - 1);
break;
case D_PATHDN:
case D_GRAYDN:
if (symName == D_PATHDN) {
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].hitextcolor]);
}
else {
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].lowcolor]);
}
MoveToEx(hdcMem, txt.left + 2 * (g_AvWidthFont / 3), (txt.bottom + txt.top) / 2, 0);
LineTo(hdcMem, txt.left + 3, (txt.bottom + txt.top) / 2);
LineTo(hdcMem, txt.left + 1, (txt.bottom + txt.top) / 2 + 2);
LineTo(hdcMem, txt.left + 1, txt.bottom);
break;
case D_PATHDNEND:
case D_GRAYDNEND:
if (symName == D_PATHDNEND) {
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].hitextcolor]);
}
else {
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].lowcolor]);
}
MoveToEx(hdcMem, txt.left + 1, txt.top, 0);
LineTo(hdcMem, txt.left + 1, (txt.bottom + txt.top) / 2 - 1);
LineTo(hdcMem, txt.left + 2, (txt.bottom + txt.top) / 2);
LineTo(hdcMem, g_AvWidthFont + txt.left - 1, (txt.bottom + txt.top) / 2);
LineTo(hdcMem, g_AvWidthFont + txt.left - 4, (txt.bottom + txt.top) / 2 - 3);
MoveToEx(hdcMem, g_AvWidthFont + txt.left - 1, (txt.bottom + txt.top) / 2, 0);
LineTo(hdcMem, g_AvWidthFont + txt.left - 4, (txt.bottom + txt.top) / 2 + 3);
break;
case 'h':
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].hitextcolor]);
MoveToEx(hdcMem, txt.left + 2 * (g_AvWidthFont / 3), (txt.bottom + txt.top) / 2, 0);
LineTo(hdcMem, txt.left + 3, (txt.bottom + txt.top) / 2);
LineTo(hdcMem, txt.left + 1, (txt.bottom + txt.top) / 2 + 2);
LineTo(hdcMem, txt.left + 1, txt.bottom);
MoveToEx(hdcMem, txt.left + 1, txt.top, 0);
LineTo(hdcMem, txt.left + 1, (txt.bottom + txt.top) / 2 + 1);
break;
case D_PATH:
case D_GRAYPATH:
if (symName == D_PATH) {
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].hitextcolor]);
}
else {
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].lowcolor]);
}
MoveToEx(hdcMem, txt.left + 1, txt.top, 0);
LineTo(hdcMem, txt.left + 1, txt.bottom);
break;
case D_LASTCASE:
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].condbkcolor]);
MoveToEx(hdcMem, txt.left, txt.top, 0);
LineTo(hdcMem, txt.left, txt.top + fontHeight / 2 + 1);
MoveToEx(hdcMem, txt.left + 1, txt.top, 0);
LineTo(hdcMem, txt.left + 1, txt.top + fontHeight / 2 + 2);
MoveToEx(hdcMem, txt.left + 2, txt.top + fontHeight / 2, 0);
LineTo(hdcMem, txt.left + 5, txt.top + fontHeight / 2);
MoveToEx(hdcMem, txt.left + 2, txt.top + fontHeight / 2 - 2, 0);
LineTo(hdcMem, txt.left + 2, txt.top + fontHeight / 2 + 3);
MoveToEx(hdcMem, txt.left + 3, txt.top + fontHeight / 2 - 1, 0);
LineTo(hdcMem, txt.left + 3, txt.top + fontHeight / 2 + 2);
break;
case D_PATHUPEND:
case D_GRAYUPEND:
if (symName == D_PATHUPEND) {
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].hitextcolor]);
}
else {
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].lowcolor]);
}
MoveToEx(hdcMem, txt.left + 2 * (g_AvWidthFont / 3), (txt.bottom + txt.top) / 2, 0);
LineTo(hdcMem, txt.left + 3, (txt.bottom + txt.top) / 2);
LineTo(hdcMem, txt.left + 1, (txt.bottom + txt.top) / 2 - 2);
LineTo(hdcMem, txt.left + 1, txt.top - 1);
break;
case D_PATHUP:
case D_GRAYUP:
if (symName == D_PATHUP) {
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].hitextcolor]);
}
else {
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].lowcolor]);
}
MoveToEx(hdcMem, txt.left + 2 * (g_AvWidthFont / 3), (txt.bottom + txt.top) / 2, 0);
LineTo(hdcMem, txt.left + 3, (txt.bottom + txt.top) / 2);
LineTo(hdcMem, txt.left + 1, (txt.bottom + txt.top) / 2 - 2);
LineTo(hdcMem, txt.left + 1, txt.top - 1);
break;
case 'z':
SelectObject(hdcMem, g_myPen[g_myScheme[m_Table.scheme].hitextcolor]);
MoveToEx(hdcMem, txt.left + 1, txt.top, 0);
LineTo(hdcMem, txt.left + 1, (txt.bottom + txt.top) / 2 - 1);
LineTo(hdcMem, txt.left + 2, (txt.bottom + txt.top) / 2);
LineTo(hdcMem, g_AvWidthFont + txt.left - 1, (txt.bottom + txt.top) / 2);
LineTo(hdcMem, g_AvWidthFont + txt.left - 4, (txt.bottom + txt.top) / 2 - 3);
MoveToEx(hdcMem, txt.left + 1, txt.bottom - 1, 0);
LineTo(hdcMem, txt.left + 1, (txt.bottom + txt.top) / 2 + 1);
LineTo(hdcMem, txt.left + 2, (txt.bottom + txt.top) / 2);
MoveToEx(hdcMem, g_AvWidthFont + txt.left - 1, (txt.bottom + txt.top) / 2, 0);
LineTo(hdcMem, g_AvWidthFont + txt.left - 4, (txt.bottom + txt.top) / 2 + 3);
break;
default:
break;
}
}
symName = 0;
j = k;
txt.left = txt.right; // 下一个文本位置
}
if (txt.left >= entry.right)
break;
if (mask & DRAW_GRAPH) {
if (select & DRAW_UNICODE) {
symName = s[j];
}
else {
symName = t.at(j);
}
}
drawMask = mask;
if (!(drawMask & DRAW_MASK)) {
drawMask &= ~DRAW_GRAPH;
}
k++;
txt.right += g_AvWidthFont;
}
if (entry.right > txt.left) {
txt.right = entry.right;
if (select & DRAW_SELECT) {
iBkColor = g_myScheme[m_Table.scheme].selbkcolor;
}
else {
iBkColor = g_myScheme[m_Table.scheme].bkcolor;
}
FillRect(hdcMem, &txt, g_myBrush[iBkColor]);
}
}
else {
int opt;
if (select & DRAW_GRAY) {
iTxColor = g_myScheme[m_Table.scheme].lowcolor;
}
else if (select & DRAW_HILITE) {
iTxColor = g_myScheme[m_Table.scheme].hitextcolor;
}
else {
iTxColor = g_myScheme[m_Table.scheme].textcolor;
}
if (select & DRAW_EIP) {
if (select & DRAW_BREAK) {
iTxColor = g_myScheme[m_Table.scheme].hitextcolor;
}
else {
iTxColor = g_myScheme[m_Table.scheme].bkcolor;
}
iBkColor = g_myScheme[m_Table.scheme].textcolor;
}
else if (select & DRAW_BREAK) {
iTxColor = g_myScheme[m_Table.scheme].textcolor;
iBkColor = g_myScheme[m_Table.scheme].hitextcolor;
}
else if (select & DRAW_SELECT) {
iBkColor = g_myScheme[m_Table.scheme].selbkcolor;
}
else {
iBkColor = g_myScheme[m_Table.scheme].bkcolor;
}
SetTextColor(hdcMem, g_myColor[iTxColor]);
SetBkColor(hdcMem, g_myColor[iBkColor]);
bottom = entry.bottom;
if (select & DRAW_TOP) {
entry.bottom -= fontHeight / 2;
FillRect(hdcMem, &entry, g_myBrush[g_myScheme[m_Table.scheme].bkcolor]);
entry.top += fontHeight;
entry.bottom += fontHeight / 2;
bottom += fontHeight / 2;
}
else if (select & DRAW_BOTTOM) {
entry.bottom -= fontHeight - fontHeight / 2;
bottom += fontHeight / 2;
}
if ((select & (DRAW_BREAK | DRAW_SELECT)) == (DRAW_BREAK | DRAW_SELECT)) {
FillRect(hdcMem, &entry, g_myBrush[g_myScheme[m_Table.scheme].condbkcolor]);
opt = ETO_CLIPPED;
}
else {
opt = ETO_CLIPPED | ETO_OPAQUE;
}
if (select & DRAW_UNICODE) {
ExtTextOutW(hdcMem, entry.left + g_AvWidthFont / 2, bottom, opt, &entry, s.GetString(), len, NULL);
}
else {
ExtTextOutA(hdcMem, entry.left + g_AvWidthFont / 2, bottom, opt, &entry, t.c_str(), t.length(), NULL);
}
if (select & DRAW_TOP) {
entry.top -= fontHeight / 2;
}
else if (select & DRAW_BOTTOM) {
entry.bottom += fontHeight - fontHeight / 2;
entry.top += fontHeight - fontHeight / 2;
FillRect(hdcMem, &entry, g_myBrush[1]);
entry.top -= fontHeight - fontHeight / 2;
}
}
}
}
else {
FillRect(hdcMem, &entry, g_myBrush[g_myScheme[scheme].auxcolor]);
}
SelectObject(hdcMem, g_myPen[g_myScheme[scheme].linecolor]);
MoveToEx(hdcMem, entry.right, entry.top, 0);
LineTo(hdcMem, entry.right, entry.bottom); // 短的分割线
entry.left = entry.right + 1; // 下一个表项位置
col++; // 下一个entry
}
if (row.right > entry.left) {
entry.right = row.right;
FillRect(hdcMem, &entry, g_myBrush[g_myScheme[m_Table.scheme].bkcolor]);
}
int height;
if (m_Table.mode & TABLE_DIR) {
if (m_bSnowFreeDrawing) {
height = row.bottom - row.top;
BitBlt(hdc, row.left, row.top, row.right - row.left, row.bottom - row.top, hdcMem, row.left,
fontHeight - (row.bottom - row.top),
SRCCOPY);
}
row.bottom = row.top;
}
else {
if (m_bSnowFreeDrawing) {
BitBlt(hdc, row.left, row.top, row.right - row.left, fontHeight, hdcMem, row.left, 0, SRCCOPY);
}
row.top = row.bottom;
}
}
if (!(m_Table.mode & TABLE_DIR) && row.top<client.bottom || m_Table.mode & TABLE_DIR
&& row.bottom>client.top) {
SelectObject(hdc, g_myPen[g_myScheme[m_Table.scheme].linecolor]);
if (m_Table.mode & TABLE_DIR) {
row.top = client.top;
}
else {
row.bottom = client.bottom;
}
for (int m = 0; m < m_Bar.nbar; m++) {
int dx = m_Bar.dx[m];
row.right = row.left + dx - 1;
if (dx > 3) {
FillRect(hdc, &row, g_myBrush[g_myScheme[m_Table.scheme].bkcolor]);
}
else {
FillRect(hdc, &row, g_myBrush[g_myScheme[m_Table.scheme].auxcolor]);
}
MoveToEx(hdc, row.right, row.top, NULL);
LineTo(hdc, row.right, row.bottom);
row.left = row.right + 1;
}
if (client.right > row.left) { // 处理表格外的
row.right = client.right;
FillRect(hdc, &row, g_myBrush[g_myScheme[m_Table.scheme].bkcolor]);
}
}
if (m_bSnowFreeDrawing) {
SelectObject(hdcMem, hgdiMem);
DeleteObject(hBitmap);
DeleteDC(hdcMem);
}
EndPaint(hw, &ps);
}
else {
FillRect(hdc, &client, g_myBrush[g_myScheme[m_Table.scheme].bkcolor]);
EndPaint(hw, &ps);
}
}
template<class T>
void CTable<T>::SetTableWindowInfo(int maxColumns,int nlines) {
ATLASSERT(nlines > 5 && maxColumns > 2);
m_Rect.right = GetSystemMetrics(SM_CXVSCROLL) - 1;
int j = 0;
while (m_Bar.nbar > j && j < maxColumns) {
if (m_Bar.nbar - 1 != j || m_Bar.defdx[j] != 256) {
m_Rect.right += m_Bar.defdx[j];
}
else {
m_Rect.right += 50 * g_AvWidthFont;
}
++j;
}
m_Rect.bottom = nlines * g_AvHighFont;
if (m_Table.hscroll == 1) {
m_Rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
m_Rect.bottom += g_AvHighFont + 4;
}
AdjustWindowRect(&m_Rect, WS_CHILD | WS_GROUP | WS_TABSTOP | WS_SYSMENU | WS_THICKFRAME | WS_CAPTION, false);
m_Rect.right -= m_Rect.left;
m_Rect.bottom -= m_Rect.top;
RECT client;
GetClientRect(g_hWndMDIClient, &client);
_style = WS_CHILD | WS_GROUP | WS_TABSTOP | WS_CLIPSIBLINGS
| WS_VISIBLE | WS_VSCROLL | WS_SYSMENU | WS_THICKFRAME | WS_CAPTION;
m_Rect.top = CW_USEDEFAULT;
m_Rect.left = CW_USEDEFAULT;
if (!(m_Table.mode & TABLE_NOHSCR)) {
_style = WS_CHILD | WS_GROUP | WS_TABSTOP | WS_CLIPSIBLINGS
| WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | WS_SYSMENU | WS_THICKFRAME | WS_CAPTION;
}
if (client.right < m_Rect.right) {
m_Rect.right = client.right;
}
if (client.bottom < m_Rect.bottom) {
m_Rect.bottom = client.bottom;
}
}
template<class T>
int CTable<T>::Tablefunction(HWND hw, UINT msg, WPARAM wp, LPARAM lp) {
RECT client, bar;
int bottomRow;
int xPos=0, yPos = 0;
WPARAM col = -1;
int newdx;
bool pressShiftKey, pressCtrlKey;
int ret = 0;
int selRow;
GetClientRect(hw, &client);
memcpy(&bar, &client, sizeof(bar));
if (m_Table.showbar == 1) {
client.top = g_AvHighFont + 4;
bar.bottom = g_AvHighFont + 4;
}
else {
bar.bottom = bar.top;
}
int rows = (client.bottom - client.top) / g_AvHighFont;
if (rows <= 0) {
rows = 1;
}
if (m_Table.mode & TABLE_DIR) {
bottomRow = -1;
}
else {
bottomRow = 1;
}
bool onBar = false;
int xshift;
int iHScrollPos, iVScrollPos;
int lines;
int iSplitLine = -1, left=0, x;
if (msg == WM_MOUSEMOVE || WM_LBUTTONDOWN == msg || msg == WM_LBUTTONDBLCLK || msg == WM_LBUTTONUP
|| msg == WM_RBUTTONDOWN || (msg == WM_TIMER && wp == 1)) {
if (msg == WM_TIMER) {
xPos = m_Bar.prevx;
yPos = -1;
}
else {
xPos = GET_X_LPARAM(lp);
yPos = GET_Y_LPARAM(lp);
}
onBar = yPos >= bar.top && yPos < bar.bottom;
if (!onBar&&msg==WM_RBUTTONDOWN) {
Tablefunction(hw, WM_LBUTTONDOWN, wp, lp);
}
if (bottomRow < 0) {
yPos = client.bottom + client.top - yPos - 1;
}
int j = 0;
xshift = -m_Table.xshift - 1;
while (j < m_Bar.nbar && j < NBAR) {
x = xshift + m_Bar.dx[j];
if (abs(xPos - x) <= 1 && !(m_Bar.mode[j] & BAR_NORESIZE)) {
iSplitLine = j;
}
if (xPos >= xshift && x > xPos) {
col = j;
left = xPos - xshift - 1;
if (!(m_Bar.mode[j] & BAR_SHIFTSEL)) {
left -= g_AvWidthFont / 2;
}
if (left < 0) {
left = 0;
}
}
xshift = x;
j++;
}
}
switch (msg) {
case WM_RBUTTONDOWN:
{
return onBar ? false : true;
}
case WM_HSCROLL:
{
newdx = -client.right;
int i = 0;
while (i < m_Bar.nbar) {
newdx += m_Bar.dx[i];
++i;
}
iHScrollPos = m_Table.xshift;
switch (LOWORD(wp)) {
case SB_LINELEFT:
iHScrollPos -= g_AvWidthFont;
break;
case SB_LINERIGHT:
iHScrollPos += g_AvWidthFont;
break;
case SB_PAGELEFT:
iHScrollPos -= 8 * g_AvWidthFont;
break;
case SB_LEFT:
iHScrollPos = 0;
break;
case SB_RIGHT:
iHScrollPos = newdx;
break;
case SB_THUMBTRACK:
iHScrollPos = MulDiv(HIWORD(wp), newdx, 0x4000);
break;
default:
break;
}
if (iHScrollPos > newdx) {
iHScrollPos = newdx;
}
if (iHScrollPos < 0) {
iHScrollPos = 0;
}
if (iHScrollPos != m_Table.xshift) {
m_Table.xshift = iHScrollPos;
InvalidateRect(hw, nullptr, false);
}
return 0;
}
case WM_USER_SCR:
{
LONG style = GetWindowLong(hw, GWL_STYLE);
if (style & WS_VSCROLL) {
SetScrollRange(hw, SB_VERT, 0, 0x4000, false);
ret = SendMessage(hw, WM_USER_VABS, rows, 0);
if (ret < 0)
ret = 0x4000 - ret;
if (m_Table.offset != 0&& ret == 0) {
ret = MulDiv(m_Table.offset+rows, 0x4000,m_Table.data.n);
}
if (ret != GetScrollPos(hw, SB_VERT)) {
SetScrollPos(hw, SB_VERT, ret, true);
}
}
if (style & WS_HSCROLL) {
SetScrollRange(hw, SB_HORZ, 0, 0x4000, false);
newdx = -client.right;
int i = 0;
while (i < m_Bar.nbar) {
newdx += m_Bar.dx[i];
++i;
}
int nPos;
nPos = MulDiv(m_Table.xshift, 0x4000, newdx);
SetScrollPos(hw, SB_HORZ, nPos, true);
}
return 0;
}
case WM_DESTROY:
{
if (hw == g_hWndTop)
g_hWndTop = 0;
if (m_Table.mode & TABLE_SAVEPOS) {
}
return 0;
}
case WM_USER_VABS:
{
selRow = lp + m_Table.offset;
if (selRow > (signed int)(m_Table.data.n - wp)) {
selRow = m_Table.data.n - wp;
}
if (selRow < 0) {
selRow = 0;
}
m_Table.offset = selRow;
if (selRow) {
return MulDiv(selRow, 0x4000, m_Table.data.n - wp);
}
else {
return 0;
}
}
case WM_USER_VREL:
{
if (m_Table.data.n > wp) {
selRow = MulDiv(m_Table.data.n - wp, lp, 0x4000);
}
else {
selRow = 0;
}
if (selRow > (signed int)(m_Table.data.n - wp)) {
selRow = m_Table.data.n - wp;
}
if (selRow < 0) {
selRow = 0;
}
if (lp && selRow == m_Table.offset) {
return -1;
}
else {
m_Table.offset = selRow;
if (selRow) {
return MulDiv(selRow, 0x4000, m_Table.data.n - wp);
}
else {
return 0;
}
}
}
case WM_VSCROLL:
{
pressShiftKey = GetKeyState(VK_SHIFT) & 0x8000;
switch (LOWORD(wp)) {
case SB_LINEDOWN:
if (pressShiftKey && m_Table.mode & TABLE_USERDEF) {
ret = SendMessage(hw, WM_USER_VBYTE, rows, bottomRow);
}
else {
ret = SendMessage(hw, WM_USER_VABS, rows, bottomRow);
}
break;
case SB_LINEUP:
if (pressShiftKey && m_Table.mode & TABLE_USERDEF) {
ret = SendMessage(hw, WM_USER_VBYTE, rows, -bottomRow);
}
else {
ret = SendMessage(hw, WM_USER_VABS, rows, -bottomRow);
}
break;
case SB_PAGEUP:
lines = rows - 1;
if (lines <= 0)
lines = 1;
ret = SendMessage(hw, WM_USER_VABS, rows, bottomRow * -lines);
break;
case SB_PAGEDOWN:
lines = rows - 1;
if (lines <= 0)
lines = 1;
ret = SendMessage(hw, WM_USER_VABS, rows, bottomRow * lines);
break;
case SB_THUMBTRACK:
iVScrollPos = HIWORD(wp);
if (bottomRow < 0)
iVScrollPos = 0x3ff - iVScrollPos;
ret = ::SendMessage(hw, WM_USER_VREL, rows, iVScrollPos);
break;
default:
ret = -1;
break;
}
if (ret >= 0) {
if (m_Table.mode & TABLE_FASTSEL) {
RedrawWindow(hw, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
}
else {
InvalidateRect(hw, NULL, false);
}
}
return 0;
}
case WM_MOUSEMOVE:
{
HCURSOR hCursor;
if (m_Bar.captured && GetCapture() == hw) {
switch (m_Bar.captured) {
case CAPT_SPLIT:
hCursor = LoadCursor(NULL, IDC_SIZEWE);
SetCursor(hCursor);
newdx = xPos + m_Bar.dx[m_Bar.active] - m_Bar.prevx;
if (newdx < 3) {
int distance = 3 - newdx;
newdx = 3;
xPos += distance;
}
if (m_Bar.dx[m_Bar.active] != newdx) {
m_Bar.dx[m_Bar.active] = newdx;
InvalidateRect(hw, nullptr, false);
}
break;
case CAPT_BAR:
hCursor = LoadCursor(NULL, IDC_ARROW);
SetCursor(hCursor);
if (!onBar, m_Bar.active != col || m_Bar.mode[m_Bar.active] & BAR_PRESSED) {
m_Bar.mode[m_Bar.active] &= ~BAR_PRESSED;
InvalidateRect(hw, &bar, false);
}
else {
m_Bar.mode[m_Bar.active] |= BAR_PRESSED;
InvalidateRect(hw, &bar, false);
}
break;
case CAPT_DATA:
hCursor = LoadCursor(NULL, IDC_ARROW);
SetCursor(hCursor);
if (yPos < client.top || yPos >= client.bottom) {
if (yPos >= client.bottom) {
if (m_Bar.active <= 0) {
SetTimer(hw, 1, 50, NULL);
}
m_Bar.active = 1;
if (client.bottom + 48 < yPos) {
m_Bar.active += (yPos - client.bottom - 48) / 16;
}
}
else {
if (m_Bar.active >= 0) {
SetTimer(hw, 1, 50, NULL);
}
m_Bar.active = -1;
if (client.top - 48 > yPos) {
m_Bar.active -= (client.top - 48 - yPos) / 16;
}
}
}
else {
KillTimer(hw, 1);
m_Bar.active = 0;
if (SendMessage(hw, WM_USER_CNTS, col << 16 | LOWORD(left / g_AvWidthFont),
(yPos - client.top) / g_AvHighFont)) {
if (m_Table.mode & TABLE_FASTSEL) {
RedrawWindow(hw, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
}
else {
InvalidateRect(hw, NULL, false);
}
}
}
break;
}
m_Bar.prevx = xPos;
}
else if (iSplitLine < 0) {
hCursor = LoadCursor(NULL, IDC_ARROW);
SetCursor(hCursor);
}
else {
hCursor = LoadCursor(NULL, IDC_SIZEWE);
SetCursor(hCursor);
}
return 0;
}
case WM_LBUTTONDBLCLK: {
bool handle = onBar || iSplitLine >= 0 ||
SendMessage(hw, WM_USER_DBLCLK, ((uint16_t)col << 16) | (uint16_t)(left / g_AvWidthFont), (yPos - client.top) / g_AvHighFont) != 1;
if (!handle)
break;
}
case WM_LBUTTONDOWN:
{
SetFocus(hw);
if (iSplitLine < 0) {
if (!onBar || (col & 0x80000000) != 0 || m_Bar.mode[col] & (BAR_NOSORT | BAR_DISABLED)) {
if (!onBar || (col & 0x80000000) != 0) {
pressShiftKey = GetKeyState(VK_SHIFT) & 0x800;
UINT uMsg = WM_USER_CNTS;
if (!pressShiftKey) {
uMsg = WM_USER_STS;
}
int value = SendMessage(hw, uMsg, col << 16 | LOWORD(left / g_AvWidthFont),
(yPos - client.top) / g_AvHighFont);
if (value > 0) {
if (m_Table.mode & TABLE_FASTSEL) {
RedrawWindow(hw, nullptr, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
}
else {
InvalidateRect(hw, nullptr, false);
}
}
if (value >= 0) {
SetCapture(hw);
m_Bar.captured = CAPT_DATA;
m_Bar.active = 0;
}
}
}
else {
SetCapture(hw);
m_Bar.captured = CAPT_BAR;
m_Bar.mode[col] |= BAR_PRESSED;
m_Bar.active = col;
InvalidateRect(hw, &bar, false);
}
}
else {
SetCapture(hw);
m_Bar.captured = CAPT_SPLIT;
m_Bar.active = iSplitLine;
m_Bar.prevx = xPos;
}
return 0;
}
case WM_LBUTTONUP:
{
if (GetCapture() == hw) {
ReleaseCapture();
if (m_Bar.captured == CAPT_BAR) {
if (m_Bar.mode[m_Bar.active] & BAR_PRESSED) {
m_Bar.mode[m_Bar.active] &= ~BAR_PRESSED;
if (m_Bar.mode[m_Bar.active] & BAR_BUTTON) {
InvalidateRect(hw, &bar, false);
SendMessage(hw, WM_USER_BAR, m_Bar.active, 0);
}
else if (Sortsorteddata(m_Bar.active)) {
InvalidateRect(hw, nullptr, false);// 重新排序了,则刷新整个窗口
}
else {
InvalidateRect(hw, &bar, false);
}
}
}
else if (m_Bar.captured == CAPT_DATA) {
KillTimer(hw, 1);
}
m_Bar.captured = CAPT_FREE;
}
return 0;
}
case WM_USER_CNTS:
case WM_USER_STS:
{
if (m_Table.mode & TABLE_USERDEF) {
return 0;
}
int selRow = lp + m_Table.offset;
if (selRow >= m_Table.data.n) {
selRow = m_Table.data.n - 1;
}
if (selRow == m_Table.data.selected && (!(m_Table.mode & TABLE_COLSEL)
|| HIWORD(lp) == m_Table.colsel)) {
return 0;
}
if (selRow > 0) {
auto item = Getsortedbyselection(selRow);
m_Table.data.seladdr = GetSeladdr(item);
}
m_Table.data.selected = selRow;
if (m_Table.mode & TABLE_COLSEL) {
m_Table.colsel = HIWORD(wp);
}
else {
m_Table.colsel = 0;
}
return 1;
}
case WM_WINDOWPOSCHANGED:
{
if (*(HWND*)lp != g_hWndTop && g_hWndTop) {
SetWindowPos(g_hWndTop, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOMOVE);
}
return DefMDIChildProc(g_hWndTop, WM_WINDOWPOSCHANGED, wp, lp);
}
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
{
GetSysKeyState(msg, lp, pressShiftKey, pressCtrlKey);
int count = lp & 0x7FFF;
if (count != 0) {
if (count > 0x10) {
count = 16;
}
}
else {
count = 1;
}
int shift;
if (wp == VK_LEFT) {
int colsel = m_Table.colsel;
if (pressCtrlKey) {
xshift = 0;
for (int i = 0; i < m_Bar.nbar && xshift + m_Bar.dx[i] < m_Table.xshift; i++) {
xshift += m_Bar.dx[i];
}
}
else if (m_Table.mode & TABLE_COLSEL) {
--colsel;
xshift = m_Table.xshift;
int width;
do {
width = m_Bar.dx[colsel];
--colsel;
} while (colsel >= 0 && width <= 3);
if (colsel < 0) {
colsel = m_Table.colsel;
}
else {
xshift = 0;
for (int i = 0; colsel > i; i++) {
xshift += m_Bar.dx[i];
}
if (xshift > m_Table.xshift) {
xshift = m_Table.xshift;
}
}
}
else {
xshift = m_Table.xshift - count * g_AvWidthFont;
}
if (xshift < 0) {
xshift = 0;
}
if (xshift != m_Table.xshift || colsel != m_Table.colsel) {
m_Table.xshift = xshift;
m_Table.colsel = colsel;
InvalidateRect(hw, nullptr, NULL);
}
return 1;
}
else if (wp == VK_RIGHT) {
int col = m_Table.colsel;
int newdx = 0;
if (pressCtrlKey) {
shift = 0;
for (int i = 0; i < m_Bar.nbar; i++) {
if (m_Table.xshift >= newdx && i < m_Bar.nbar - 1) {
shift += m_Bar.dx[i];
}
newdx += m_Bar.dx[i];
}
}
else if (m_Table.mode & TABLE_COLSEL) {
int tmp;
do {
tmp = m_Bar.dx[col];
col++;
} while (col < m_Bar.nbar && tmp <= 3);
if (col >= m_Bar.nbar) {
for (int i = 0; i < m_Bar.nbar; i++) {
newdx += m_Bar.dx[i];
}
col = m_Table.colsel;
shift = m_Table.xshift;
}
else {
shift = 0;
for (int i = 0; col > i; i++) {
shift += m_Bar.dx[i];
}
newdx = shift + m_Bar.dx[col];
}
}
else {
for (int i = 0; i < m_Bar.nbar; i++) {
newdx += m_Bar.dx[i];
}
shift = count * g_AvWidthFont + m_Table.xshift;
}
newdx -= client.right;
if (shift > newdx) {
shift = newdx;
}
if (shift < 0)
shift = 0;
if (shift != m_Table.xshift || col != m_Table.colsel) {
m_Table.xshift = shift;
m_Table.colsel = col;
InvalidateRect(hw, nullptr, false);
}
return 1;
}
else {
lines = count * bottomRow;
switch (wp) {
case VK_PRIOR:
{
int totalRow = rows - 1;
if (totalRow <= 0) {
totalRow = 1;
}
_page = lines * -totalRow;
LPARAM lParam;
if (pressCtrlKey) {
lParam = 0x7FFFFFFF;
}
else {
lParam = _page;
}
ret = SendMessage(hw, WM_USER_CHGS, rows, lParam);
break;
}
case VK_NEXT:
{
int totalRow = rows - 1;
if (totalRow <= 0) {
totalRow = 1;
}
_page = lines * totalRow;
LPARAM lParam;
if (pressCtrlKey) {
lParam = 0x7FFFFFFF;
}
else {
lParam = _page;
}
ret = SendMessage(hw, WM_USER_CHGS, rows, lParam);
break;
}
case VK_END:
{
ret = SendMessage(hw, WM_USER_CHGS, rows, 0x7FFFFFFE);
break;
}
case VK_HOME:
{
ret = SendMessage(hw, WM_USER_CHGS, rows, 0x7FFFFFFF);
break;
}
case VK_UP:
{
if (pressCtrlKey && m_Table.mode & TABLE_USERDEF) {
ret = SendMessage(hw, WM_USER_VBYTE, rows, -lines);
}
else {
ret = SendMessage(hw, WM_USER_CHGS, rows, -lines);
}
break;
}
case VK_DOWN:
{
if (pressCtrlKey && m_Table.mode & TABLE_USERDEF) {
ret = SendMessage(hw, WM_USER_VBYTE, rows, lines);
}
else {
ret = SendMessage(hw, WM_USER_CHGS, rows, lines);
}
break;
}
default:
break;
}
if (ret >= 0) {
if (m_Table.mode & TABLE_FASTSEL) {
RedrawWindow(hw, nullptr, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
}
else {
InvalidateRect(hw, nullptr, false);
}
}
return 1;
}
}
case WM_USER_CHGS:
{
if (lp == 0x7FFFFFFF) {
if (bottomRow <= 0) {
selRow = m_Table.data.n - 1;
}
else {
selRow = 0;
}
}
else if (lp == 0x7FFFFFFE) {
if (bottomRow <= 0) {
selRow = 0;
}
else {
selRow = m_Table.data.n - 1;
}
}
else {
selRow = lp + m_Table.data.selected;
}
if (selRow >= m_Table.data.n) {
selRow = m_Table.data.n - 1;
}
if (selRow < 0)
selRow = 0;
if (selRow == m_Table.data.selected)
return -1;
auto item = Getsortedbyselection(selRow);
ulong addr = GetSeladdr(item);
m_Table.data.selected = selRow;
if (addr) {
m_Table.data.seladdr = addr;
}
int offset = _page + m_Table.offset;
if (selRow >= offset + wp) {
offset = selRow - wp + 1;
}
if (selRow < offset)
offset = selRow;
if (offset > (signed int)(m_Table.data.n - wp)) {
offset = m_Table.data.n - wp;
}
if (offset < 0)
offset = 0;
m_Table.offset = offset;
if (offset) {
return MulDiv(offset, 0x4000, m_Table.data.n - wp);
}
else {
return 0;
}
}
}
return 1;
}