Advertisement
Old_But_Gold

Untitled

Oct 30th, 2024
12
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.13 KB | None | 0 0
  1. #define _CRT_SECURE_NO_WARNINGS
  2.  
  3. #include "Table.h"
  4.  
  5. int Table::GetItemHeight()
  6. {
  7. return itemHeight;
  8. }
  9.  
  10. void Table::SetItemHeight(int item_height)
  11. {
  12. this->itemHeight = item_height;
  13. }
  14.  
  15. bool Table::RegisterCustomListClass(HINSTANCE hInstance, std::wstring className) {
  16. WNDCLASS wc = {};
  17. wc.lpfnWndProc = Table::CustomListWndProc;
  18. wc.hInstance = hInstance;
  19. wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
  20. wc.lpszClassName = className.c_str();
  21. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  22.  
  23. return RegisterClass(&wc);
  24. }
  25.  
  26. Table::Table(HWND parent, int rows, int cols, HFONT hHeaderFont, HFONT hCellFont)
  27. : hwndParent(parent), rowCount(rows) {
  28. this->itemHeight = ITEM_HEIGHT;
  29. this->selectedItem = -1;
  30. this->selectedColumn = -1;
  31. this->scrollPos = 0;
  32. this->resizingColumn = -1;
  33. this->resizeStartX = 0;
  34. this->resizeStartWidth = 0;
  35.  
  36. this->ignoreNextLButtonDown = false;
  37. this->ignoreNextLButtonUp = false;
  38.  
  39. this->ignoreNextRButtonDown = false;
  40. this->ignoreNextRButtonUp = false;
  41.  
  42. this->hHeaderFont = hHeaderFont;
  43. this->hCellFont = hCellFont;
  44.  
  45. this->header = new HeaderTable(cols, SCREEN_WIDTH);
  46.  
  47. this->items.resize(rows, CustomListItem());
  48. for (int i = 0; i < rows; i++) {
  49. if (i % 2 == 0)
  50. {
  51. this->items[i].columns.resize(cols, Cell(L"", true));
  52. } else
  53. {
  54. this->items[i].columns.resize(cols, Cell(L"", false));
  55. }
  56. }
  57.  
  58. this->hwnd = CreateWindowEx(0, WC_CUSTOM_LIST_VIEW, L"",
  59. WS_CHILD | LVS_REPORT,
  60. 0, 0, SCREEN_WIDTH - 2, SCREEN_HEIGHT,
  61. this->hwndParent, (HMENU)ID_LIST_VIEW, (HINSTANCE)GetWindowLongPtr(this->hwndParent, GWLP_HINSTANCE), this);
  62.  
  63. this->UpdateVerticalScrollBar();
  64. }
  65.  
  66. Table::~Table() {
  67. DeleteObject(this->hHeaderFont);
  68. DeleteObject(this->hCellFont);
  69. DestroyWindow(this->hwnd);
  70. ClearItems();
  71.  
  72. if (this->hEdit) {
  73. DestroyWindow(this->hEdit);
  74. }
  75.  
  76. delete header;
  77. }
  78.  
  79. void Table::ClearItems() {
  80. for (int i = 0; i < this->items.size(); i++) {
  81. this->items[i].columns.clear();
  82. }
  83. this->items.clear();
  84.  
  85. this->scrollPos = 0;
  86. this->selectedItem = -1;
  87.  
  88. this->UpdateVerticalScrollBar();
  89.  
  90. RedrawWindow(this->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
  91. }
  92.  
  93. void Table::Show() {
  94. ShowWindow(this->hwnd, SW_SHOW);
  95. }
  96.  
  97. void Table::UnShow() {
  98. ShowWindow(this->hwnd, SW_HIDE);
  99. }
  100.  
  101. HWND Table::GetHWND() {
  102. return this->hwnd;
  103. }
  104.  
  105. HFONT Table::CreateDefaultFont() {
  106. LOGFONT logFont;
  107. ZeroMemory(&logFont, sizeof(LOGFONT));
  108. HFONT defaultFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
  109.  
  110. GetObject(defaultFont, sizeof(LOGFONT), &logFont);
  111. logFont.lfHeight = DEFAULT_FONT_SIZE;
  112. return CreateFontIndirect(&logFont);
  113. }
  114.  
  115. void Table::UpdateVerticalScrollBar() {
  116. RECT clientRect;
  117. GetClientRect(this->hwndParent, &clientRect);
  118.  
  119. int visibleRows = (clientRect.bottom - this->header->GetColumnHeight()) / this->itemHeight;
  120.  
  121. SCROLLINFO si = {};
  122. si.cbSize = sizeof(SCROLLINFO);
  123. si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
  124. si.nMin = 0;
  125. si.nMax = static_cast<int>(this->items.size()) - 1;
  126. si.nPage = visibleRows > 0 ? static_cast<UINT>(visibleRows) : 1;
  127. si.nPos = this->scrollPos;
  128.  
  129. SetScrollInfo(this->hwnd, SB_VERT, &si, TRUE);
  130. }
  131.  
  132. void Table::UpdateItemHeight() {
  133. HDC hdc = GetDC(this->hwnd);
  134.  
  135. this->header->SetColumnHeight(GetTextHeightInPixels(hdc, FONTS_TEXT_SIZE_UPDATE, this->hHeaderFont) + HEADER_PADDING * 2);
  136.  
  137. int maxTextHeight = GetTextHeightInPixels(hdc, FONTS_TEXT_SIZE_UPDATE, this->hCellFont);
  138.  
  139. this->itemHeight = maxTextHeight + HEADER_PADDING * 2;
  140.  
  141. HWND hEdit = GetDlgItem(this->hwnd, ID_ENTER_BTN_CLICKED);
  142. SetWindowPos(hEdit, NULL, hEditX, hEditY, this->header->GetColumnWidths()[0] - 2, this->header->GetColumnHeight() - 5, NULL);
  143.  
  144. ReleaseDC(this->hwnd, hdc);
  145.  
  146. this->UpdateVerticalScrollBar();
  147. }
  148.  
  149. void Table::AddColumn(int column, const std::wstring& header) {
  150. if (column < 0 || column >= this->header->GetColumnCount()) {
  151. return;
  152. }
  153.  
  154. this->header->GetColumnHeaders()[column] = header;
  155. }
  156.  
  157. void Table::AddItem(int row, int column, const std::wstring& item) {
  158. if (row < 0 || row >= this->rowCount || column < 0 || column >= this->header->GetColumnCount()) {
  159. return;
  160. }
  161.  
  162. if (row >= this->items.size()) {
  163. int size = this->items.size();
  164. this->items.resize(row + 1);
  165.  
  166. for (int i = size; i <= row; i++) {
  167. this->items[i].columns.resize(this->header->GetColumnCount());
  168. }
  169. }
  170.  
  171. this->items[row].columns[column] = Cell(item, this->items[row].columns[column].IsEditable());
  172. this->UpdateVerticalScrollBar();
  173. }
  174.  
  175. //
  176.  
  177. void Table::OnSize() {
  178. this->UpdateVerticalScrollBar();
  179. }
  180.  
  181. void Table::OnVScroll(WPARAM wParam) {
  182. SCROLLINFO si = { sizeof(SCROLLINFO), SIF_ALL };
  183. GetScrollInfo(this->hwnd, SB_VERT, &si);
  184. int pos = si.nPos;
  185.  
  186. switch (LOWORD(wParam)) {
  187. case SB_LINEUP: pos -= 1; break;
  188. case SB_LINEDOWN: pos += 1; break;
  189. case SB_PAGEUP: pos -= si.nPage; break;
  190. case SB_PAGEDOWN: pos += si.nPage; break;
  191. case SB_THUMBTRACK: pos = si.nTrackPos; break;
  192. }
  193.  
  194. pos = max(0, min(pos, si.nMax - (int)si.nPage + 1));
  195. if (pos != si.nPos) {
  196. si.nPos = pos;
  197. SetScrollInfo(this->hwnd, SB_VERT, &si, TRUE);
  198. ScrollWindow(this->hwnd, 0, (this->scrollPos - pos) * this->itemHeight, NULL, NULL);
  199. scrollPos = pos;
  200. InvalidateRect(this->hwnd, NULL, TRUE);
  201.  
  202. HWND hEdit = GetDlgItem(hwnd, ID_ENTER_BTN_CLICKED);
  203. RECT editRect;
  204. GetWindowRect(hEdit, &editRect);
  205. int newYPos = editRect.top - (this->scrollPos - pos) * this->itemHeight;
  206. SetWindowPos(hEdit, NULL, hEditX, hEditY, newYPos, this->header->GetColumnHeight() - 5, SWP_NOSIZE | SWP_NOZORDER);
  207.  
  208. SendMessage(this->hwndParent, WM_LISTVIEW_SCROLL, static_cast<WPARAM>(pos), 0);
  209. }
  210. }
  211.  
  212. void Table::OnMouseWheel(WPARAM wParam) {
  213. int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
  214.  
  215. SCROLLINFO si = { sizeof(SCROLLINFO), SIF_ALL };
  216. GetScrollInfo(this->hwnd, SB_VERT, &si);
  217.  
  218. int pos = si.nPos;
  219. int scrollAmount = -zDelta / WHEEL_DELTA * this->itemHeight;
  220.  
  221. pos += scrollAmount;
  222.  
  223. pos = max(0, min(pos, si.nMax - (int)si.nPage + 1));
  224.  
  225. if (pos != si.nPos) {
  226. si.nPos = pos;
  227. SetScrollInfo(this->hwnd, SB_VERT, &si, TRUE);
  228. ScrollWindow(this->hwnd, 0, (this->scrollPos - pos) * this->itemHeight, NULL, NULL);
  229. scrollPos = pos;
  230. InvalidateRect(this->hwnd, NULL, TRUE);
  231.  
  232. HWND hEdit = GetDlgItem(hwnd, ID_ENTER_BTN_CLICKED);
  233. if (hEdit) {
  234. RECT editRect;
  235. GetWindowRect(hEdit, &editRect);
  236. int newYPos = editRect.top - (this->scrollPos - pos) * this->itemHeight;
  237. SetWindowPos(hEdit, NULL, hEditX, hEditY, newYPos, this->header->GetColumnHeight() - 5, SWP_NOSIZE | SWP_NOZORDER);
  238. }
  239.  
  240. // �������� ��������� ������������� ���� � ���������
  241. SendMessage(this->hwndParent, WM_LISTVIEW_SCROLL, static_cast<WPARAM>(pos), 0);
  242. }
  243. }
  244.  
  245. void Table::OnLButtonUp(LPARAM lParam) {
  246. if (this->resizingColumn != -1) {
  247. WPARAM wParam = (static_cast<WPARAM>(this->resizingColumn) << 16) | (this->header->GetColumnWidths()[this->resizingColumn] & 0xFFFF);
  248.  
  249. SendMessage(this->hwndParent, WM_COLUMN_RESIZE, wParam, lParam);
  250.  
  251. this->resizingColumn = -1;
  252. }
  253. }
  254.  
  255. std::vector<CustomListItem>& Table::GetItems() {
  256. return this->items;
  257. }
  258.  
  259. int Table::GetSelectedColumn() {
  260. return this->selectedColumn;
  261. }
  262.  
  263. int Table::GetSelectedItem() {
  264. return this->selectedItem;
  265. }
  266.  
  267. HWND Table::GetHEdit() {
  268. return this->hEdit;
  269. }
  270.  
  271. void Table::SetHEdit(HWND value) {
  272. this->hEdit = value;
  273. }
  274.  
  275. bool Table::HandleColumnResize(int xPos, int yPos) {
  276. int x = MARGIN_LEFT;
  277. for (int j = 0; j < this->header->GetColumnCount(); j++) {
  278. if (abs(x + this->header->GetColumnWidths()[j] - xPos) < RESIZE_MARGIN && yPos < this->header->GetColumnHeight()) {
  279. this->resizingColumn = j;
  280. this->resizeStartX = xPos;
  281. this->resizeStartWidth = this->header->GetColumnWidths()[j];
  282. SetCapture(hwnd);
  283. return true;
  284. }
  285. x += this->header->GetColumnWidths()[j];
  286. }
  287. return false;
  288. }
  289.  
  290. bool Table::HandleHeaderClick(int xPos, int yPos, UINT uMsg, bool useSelection) {
  291. int x = MARGIN_LEFT;
  292. for (int j = 0; j < this->header->GetColumnCount(); j++) {
  293. if (xPos > x && xPos < x + this->header->GetColumnWidths()[j] && yPos < this->header->GetColumnHeight()) {
  294. if (useSelection) {
  295. selectedColumn = j;
  296. selectedItem = -1; // ���������� ��������� ������
  297. }
  298.  
  299. SendMessage(this->hwndParent, uMsg, (WPARAM)(j), 0);
  300. InvalidateRect(this->hwnd, NULL, TRUE);
  301. return true;
  302. }
  303. x += this->header->GetColumnWidths()[j];
  304. }
  305. return false;
  306. }
  307.  
  308. void Table::HandleCellClick(int xPos, int yPos, UINT uMsg, bool useSelection) {
  309. int x = MARGIN_LEFT;
  310. for (int i = 0; i < this->header->GetColumnCount(); i++) {
  311. x += this->header->GetColumnWidths()[i];
  312. }
  313.  
  314. if (xPos > x) {
  315. return;
  316. }
  317.  
  318.  
  319. int itemIndex = (yPos - this->header->GetColumnHeight()) / this->itemHeight + this->scrollPos;
  320. if (itemIndex >= 0 && itemIndex < this->items.size()) {
  321. int columnIndex = GetColumnIndexAtX(xPos);
  322.  
  323. if (useSelection) {
  324. this->selectedItem = itemIndex;
  325. this->selectedColumn = columnIndex;
  326. }
  327.  
  328. WPARAM wParam = (static_cast<WPARAM>(itemIndex) << 16) | (columnIndex & 0xFFFF);
  329. SendMessage(this->hwndParent, uMsg, wParam, 0);
  330.  
  331. InvalidateRect(this->hwnd, NULL, TRUE);
  332. }
  333. }
  334.  
  335. int Table::GetColumnIndexAtX(int xPos) {
  336. int columnIndex = 0;
  337. int xOffset = MARGIN_LEFT;
  338. for (int col = 0; col < this->header->GetColumnCount(); col++) {
  339. if (xPos >= xOffset && xPos < xOffset + this->header->GetColumnWidths()[col]) {
  340. columnIndex = col;
  341. break;
  342. }
  343. xOffset += this->header->GetColumnWidths()[col];
  344. }
  345. return columnIndex;
  346. }
  347.  
  348. void Table::OnLButtonDown(LPARAM lParam) {
  349. int xPos = GET_X_LPARAM(lParam);
  350. int yPos = GET_Y_LPARAM(lParam);
  351.  
  352. this->selectedColumn = -1;
  353. this->selectedItem = -1;
  354.  
  355. DestroyHEdit();
  356.  
  357. if (HandleColumnResize(xPos, yPos)) {
  358. return;
  359. }
  360.  
  361. if (HandleHeaderClick(xPos, yPos, WM_HEADER_CLICK, true)) {
  362. return;
  363. }
  364.  
  365. HandleCellClick(xPos, yPos, WM_CELL_CLICK, true);
  366. }
  367.  
  368. void Table::OnRButtonDown(LPARAM lParam) {
  369. int xPos = GET_X_LPARAM(lParam);
  370. int yPos = GET_Y_LPARAM(lParam);
  371.  
  372. DestroyHEdit();
  373.  
  374. if (HandleHeaderClick(xPos, yPos, WM_HEADER_RCLICK, false)) {
  375. return;
  376. }
  377.  
  378. HandleCellClick(xPos, yPos, WM_CELL_RCLICK, false);
  379. }
  380.  
  381. POINT Table::CalculateEditPosition(int itemIndex, int columnIndex) {
  382. int editX = MARGIN_LEFT;
  383. for (int i = 0; i < columnIndex; i++) {
  384. editX += this->header->GetColumnWidths()[i];
  385. }
  386.  
  387. int editY = (itemIndex != -1) ? (itemIndex - this->scrollPos) * this->itemHeight + this->header->GetColumnHeight() : 0;
  388.  
  389. return { editX, editY };
  390. }
  391.  
  392. SIZE Table::CalculateEditSize(int itemIndex, int columnIndex) {
  393. int editWidth = this->header->GetColumnWidths()[columnIndex];
  394. int editHeight = (itemIndex != -1) ? this->itemHeight : this->header->GetColumnHeight();
  395.  
  396. return { editWidth, editHeight };
  397. }
  398.  
  399. HeaderTable* Table::GetHeaderClass() {
  400. return this->header;
  401. }
  402.  
  403. WNDPROC currentEditCellProc;
  404.  
  405. LRESULT CALLBACK EditCellProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
  406. if (msg == WM_KEYDOWN && wParam == VK_RETURN) {
  407. Table* table = (Table*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  408. if (table) {
  409. // Retrieve the input text
  410. wchar_t directoryPath[MAX_PATH] = { 0 };
  411. GetWindowTextW(hwnd, directoryPath, MAX_PATH);
  412.  
  413. std::wstring text(directoryPath);
  414. if (table->GetSelectedItem() != -1) {
  415. table->GetItems()[table->GetSelectedItem()].columns[table->GetSelectedColumn()] = Cell(text, table->GetItems()[table->GetSelectedItem()].columns[table->GetSelectedColumn()].IsEditable());
  416. }
  417. else {
  418. table->GetHeaderClass()->GetColumnHeaders()[table->GetSelectedColumn()] = text;
  419. }
  420.  
  421. DestroyWindow(hwnd);
  422. table->SetHEdit(nullptr); // Clear the edit handle
  423. InvalidateRect(table->GetHWND(), NULL, TRUE); // Redraw the table to show updated data
  424. }
  425. return 0;
  426. }
  427. return CallWindowProc(currentEditCellProc, hwnd, msg, wParam, lParam);
  428. }
  429.  
  430. void Table::CreateEditControl(int itemIndex, int columnIndex, POINT editPosition, SIZE editSize) {
  431. std::wstring initialText;
  432.  
  433. if (itemIndex != -1) {
  434. initialText = this->items[itemIndex].columns[columnIndex].GetText();
  435. }
  436. else {
  437. initialText = this->header->GetColumnHeaders()[columnIndex];
  438. }
  439.  
  440. hEdit = CreateWindowEx(WS_EX_TOOLWINDOW, WC_EDIT, initialText.c_str(),
  441. WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_BORDER,
  442. editPosition.x, editPosition.y, editSize.cx, editSize.cy, this->hwnd, NULL, NULL, NULL);
  443.  
  444. // Set font for the edit control based on item index
  445. if (itemIndex != -1) {
  446. HFONT hFont = this->hCellFont;
  447. SendMessage(hEdit, WM_SETFONT, (WPARAM)hFont, TRUE);
  448. }
  449. else {
  450. SendMessage(hEdit, WM_SETFONT, (WPARAM)this->hHeaderFont, TRUE);
  451. }
  452.  
  453. SetFocus(hEdit);
  454. SetWindowLongPtr(hEdit, GWLP_USERDATA, (LONG_PTR)this);
  455. currentEditCellProc = (WNDPROC)SetWindowLongPtr(hEdit, GWLP_WNDPROC, (LONG_PTR)EditCellProc);
  456. }
  457.  
  458. void Table::DestroyHEdit() {
  459. if (hEdit) {
  460. DestroyWindow(hEdit);
  461. }
  462. }
  463.  
  464. void Table::OnLButtonDblClk(LPARAM lParam) {
  465. int xPos = GET_X_LPARAM(lParam);
  466. int yPos = GET_Y_LPARAM(lParam);
  467.  
  468. this->selectedColumn = -1;
  469. this->selectedItem = -1;
  470.  
  471. if (!HandleHeaderClick(xPos, yPos, WM_HEADER_DBLCLICK, true)) {
  472. HandleCellClick(xPos, yPos, WM_CELL_DBLCLICK, true);
  473. }
  474.  
  475. int itemIndex = this->selectedItem;
  476. int columnIndex = this->selectedColumn;
  477.  
  478. DestroyHEdit();
  479.  
  480. InvalidateRect(this->hwnd, NULL, TRUE);
  481. if (itemIndex != -1 || columnIndex != -1) {
  482. if (itemIndex != -1)
  483. {
  484. auto item = this->GetItems()[itemIndex].columns[columnIndex];
  485.  
  486. if (!item.IsEditable())
  487. {
  488. return;
  489. }
  490. }
  491.  
  492. // Calculate the position and size of the edit control
  493. POINT editPosition = CalculateEditPosition(itemIndex, columnIndex);
  494. SIZE editSize = CalculateEditSize(itemIndex, columnIndex);
  495.  
  496. // Create the edit control
  497. CreateEditControl(itemIndex, columnIndex, editPosition, editSize);
  498. }
  499. }
  500.  
  501. void Table::OnRButtonDblClk(LPARAM lParam) {
  502. int xPos = GET_X_LPARAM(lParam);
  503. int yPos = GET_Y_LPARAM(lParam);
  504.  
  505. DestroyHEdit();
  506.  
  507. if (HandleHeaderClick(xPos, yPos, WM_HEADER_RDBLCLICK, false)) {
  508. return;
  509. }
  510.  
  511. HandleCellClick(xPos, yPos, WM_CELL_RDBLCLICK, false);
  512. }
  513.  
  514. void Table::OnMouseMove(WPARAM wParam, LPARAM lParam) {
  515. if (wParam == MK_LBUTTON && this->resizingColumn != -1) {
  516. int deltaX = GET_X_LPARAM(lParam) - this->resizeStartX;
  517.  
  518. HWND hEdit = GetDlgItem(this->hwnd, ID_ENTER_BTN_CLICKED);
  519. SetWindowPos(hEdit, NULL, hEditX, hEditY, this->header->GetColumnWidths()[0] - 2, this->header->GetColumnHeight() - 5, NULL);
  520.  
  521. this->header->GetColumnWidths()[this->resizingColumn] = max(10, this->resizeStartWidth + deltaX);
  522. InvalidateRect(this->hwnd, NULL, TRUE);
  523. return;
  524. }
  525. int xPos = GET_X_LPARAM(lParam);
  526. int yPos = GET_Y_LPARAM(lParam);
  527. int x = MARGIN_LEFT;
  528. for (int j = 0; j < this->header->GetColumnHeaders().size(); j++) {
  529. if (abs(x + this->header->GetColumnWidths()[j] - xPos) < RESIZE_MARGIN && yPos < COLUMN_HEADER_HEIGHT) {
  530. SetCursor(LoadCursor(NULL, IDC_SIZEWE));
  531. return;
  532. }
  533. x += this->header->GetColumnWidths()[j];
  534. }
  535. SetCursor(LoadCursor(NULL, IDC_ARROW));
  536. }
  537.  
  538. void Table::OnSetFont(WPARAM wParam, LPARAM lParam) {
  539. if (lParam == ID_COMBOBOX_HEADER || lParam == ID_COMBOBOX_HEADER_SIZES) {
  540. this->hHeaderFont = (HFONT)wParam;
  541. SendMessage(GetDlgItem(this->hwnd, ID_ENTER_BTN_CLICKED), WM_SETFONT, (WPARAM)hHeaderFont, TRUE);
  542. }
  543. else if (lParam == ID_COMBOBOX_FILENAMES || lParam == ID_COMBOBOX_FILENAMES_SIZES) {
  544. //this->hFileNamesFont = (HFONT)wParam;
  545. }
  546. else if (lParam == ID_COMBOBOX_FILESIZES || lParam == ID_COMBOBOX_FILESIZES_SIZES) {
  547. //this->hFileSizesFont = (HFONT)wParam;
  548. }
  549. //Work with Font and send Params LPARAM and WPARAM
  550. this->UpdateItemHeight();
  551. }
  552.  
  553. void Table::OnPaint() {
  554. PAINTSTRUCT ps;
  555. HDC hdc = BeginPaint(hwnd, &ps);
  556.  
  557. // Создаём совместимый DC (контекст памяти)
  558. HDC memDC = CreateCompatibleDC(hdc);
  559.  
  560.  
  561. RECT clientRect = ps.rcPaint;
  562.  
  563. // Создаём битмап для двойной буферизации
  564. HBITMAP hbmMem = CreateCompatibleBitmap(hdc, clientRect.right, clientRect.bottom);
  565. HGDIOBJ hOldBitmap = SelectObject(memDC, hbmMem);
  566.  
  567. // Заливка фона таблицы
  568. HBRUSH hBrush = CreateSolidBrush(RGB(30, 30, 30));
  569. FillRect(memDC, &clientRect, hBrush);
  570. DeleteObject(hBrush); // Освобождаем кисть сразу после использования
  571.  
  572. int scrollBarWidth = GetSystemMetrics(SM_CXVSCROLL);
  573.  
  574. // ��������� ������ ���������� ������� �� ������ ����������
  575. int clientWidth = (clientRect.right - clientRect.left) - 2;
  576.  
  577. FillRect(memDC, &clientRect, (HBRUSH)(COLOR_WINDOW + 1));
  578.  
  579. // ��������� ����������
  580. RECT headerRect = { MARGIN_LEFT, 0, clientRect.right - 2, this->header->GetColumnHeight() };
  581. HBRUSH headerBrush = CreateSolidBrush(RGB(191, 166, 42));
  582. FillRect(memDC, &headerRect, headerBrush);
  583. DeleteObject(headerBrush); // Освобождаем кисть
  584.  
  585. // ��������� ������ ����������
  586. SetBkMode(memDC, TRANSPARENT);
  587. SetTextColor(memDC, RGB(50, 50, 50));
  588.  
  589. HPEN hThinPen = CreatePen(PS_SOLID, 1, RGB(217, 37, 187));
  590. HPEN hOldPen = (HPEN)SelectObject(memDC, hThinPen);
  591.  
  592. //������������ ����� ������
  593. MoveToEx(memDC, headerRect.right, headerRect.top, NULL);
  594. LineTo(memDC, headerRect.right, headerRect.bottom);
  595.  
  596. // �������������� ����� ��� �����������
  597. MoveToEx(memDC, MARGIN_LEFT, 0, NULL);
  598. LineTo(memDC, clientWidth, 0);
  599.  
  600. //������������ ����� ����� ����������
  601. MoveToEx(memDC, headerRect.left + MARGIN_LEFT, headerRect.top, NULL);
  602. LineTo(memDC, headerRect.left + MARGIN_LEFT, headerRect.bottom);
  603.  
  604. SelectObject(memDC, hOldPen);
  605. DeleteObject(hThinPen);
  606.  
  607. hThinPen = CreatePen(PS_SOLID, 1, RGB(50, 50, 50));
  608. hOldPen = (HPEN)SelectObject(memDC, hThinPen);
  609.  
  610. // �������������� ����� ��� �����������
  611. MoveToEx(memDC, MARGIN_LEFT, this->header->GetColumnHeight() - 1, NULL);
  612. LineTo(memDC, clientWidth, this->header->GetColumnHeight() - 1);
  613.  
  614. // ��������� ������ ����������
  615. int x = MARGIN_LEFT;
  616. for (int j = 0; j < this->header->GetColumnCount(); j++) {
  617. RECT textRect = { x + HEADER_PADDING, 0, x + this->header->GetColumnWidths()[j] - HEADER_PADDING, this->header->GetColumnHeight() };
  618. RECT highLightRect = { x + 1, 2, x + this->header->GetColumnWidths()[j], this->header->GetColumnHeight() - 1 };
  619.  
  620. if (j == selectedColumn && selectedItem == -1) {
  621. HBRUSH selectionBrush = CreateSolidBrush(RGB(180, 220, 255));
  622. FillRect(memDC, &highLightRect, selectionBrush);
  623. DeleteObject(selectionBrush);
  624. }
  625.  
  626. TextOutWithFont(memDC, &textRect, this->header->GetColumnHeaders()[j].c_str(), hHeaderFont, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_END_ELLIPSIS);
  627.  
  628. if (j != this->header->GetColumnCount() - 1)
  629. {
  630. MoveToEx(memDC, x + this->header->GetColumnWidths()[j], 1, NULL);
  631. LineTo(memDC, x + this->header->GetColumnWidths()[j], this->header->GetColumnHeight());
  632. }
  633. x += this->header->GetColumnWidths()[j];
  634. }
  635.  
  636. // ������������ ����� � ������ �������
  637. // ��������� ��������� ������
  638.  
  639. SelectObject(memDC, hOldPen);
  640. DeleteObject(hThinPen);
  641.  
  642. for (int i = scrollPos; i < items.size() && (i - scrollPos + 1) * itemHeight < clientRect.bottom; ++i) {
  643. RECT itemRect = { 0, (i - scrollPos) * itemHeight + this->header->GetColumnHeight(), clientWidth, (i - scrollPos + 1) * itemHeight + this->header->GetColumnHeight() };
  644.  
  645. SetBkColor(memDC, RGB(255, 255, 255));
  646. FillRect(memDC, &itemRect, (HBRUSH)GetStockObject(WHITE_BRUSH));
  647.  
  648. hThinPen = CreatePen(PS_SOLID, 1, RGB(217, 37, 187));
  649. hOldPen = (HPEN)SelectObject(memDC, hThinPen);
  650.  
  651. MoveToEx(memDC, itemRect.left + MARGIN_LEFT, itemRect.top, NULL);
  652. LineTo(memDC, itemRect.left + MARGIN_LEFT, itemRect.bottom);
  653.  
  654. SelectObject(memDC, hOldPen);
  655. DeleteObject(hThinPen);
  656.  
  657. hThinPen = CreatePen(PS_SOLID, 1, RGB(50, 50, 50));
  658. hOldPen = (HPEN)SelectObject(memDC, hThinPen);
  659.  
  660. // ��������� ������ ��������� �� ��������
  661. int x = 0;
  662. for (int j = 0; j < this->header->GetColumnCount(); j++) {
  663. RECT columnRect = { x + HEADER_PADDING, itemRect.top, x + this->header->GetColumnWidths()[j] - HEADER_PADDING, itemRect.bottom };
  664. RECT highLightRect = { x + 1, itemRect.top, x + this->header->GetColumnWidths()[j], itemRect.bottom };
  665.  
  666. if (i == selectedItem && j == selectedColumn) {
  667. HBRUSH selectionBrush = CreateSolidBrush(RGB(180, 220, 255));
  668. FillRect(memDC, &highLightRect, selectionBrush);
  669. DeleteObject(selectionBrush);
  670. }
  671.  
  672. if (!items[i].columns[j].GetText().empty()) {
  673. HFONT hFont = hCellFont;
  674. SelectObject(memDC, hFont);
  675. TextOutWithFont(memDC, &columnRect, items[i].columns[j].GetText().c_str(), hFont, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
  676. }
  677. // ������������ ����� ����� ���������
  678.  
  679. if (j != this->header->GetColumnCount() - 1)
  680. {
  681. MoveToEx(memDC, x + this->header->GetColumnWidths()[j], itemRect.top, NULL);
  682. LineTo(memDC, x + this->header->GetColumnWidths()[j], itemRect.bottom);
  683. }
  684. x += this->header->GetColumnWidths()[j];
  685.  
  686. //����� ��� ������������ �����
  687. //MoveToEx(hdc, x, clientRect.top, NULL);
  688. //LineTo(hdc, x, clientRect.bottom);
  689. }
  690.  
  691.  
  692.  
  693. // �������������� ����� ��� ������� ���������
  694. if (i == items.size() - 1) {
  695. SelectObject(memDC, hOldPen);
  696. DeleteObject(hThinPen);
  697.  
  698. hThinPen = CreatePen(PS_SOLID, 1, RGB(217, 37, 187));
  699. hOldPen = (HPEN)SelectObject(memDC, hThinPen);
  700. } else
  701. {
  702. SelectObject(memDC, hOldPen);
  703. DeleteObject(hThinPen);
  704. }
  705.  
  706. MoveToEx(memDC, 0, itemRect.bottom - 1, NULL);
  707. LineTo(memDC, clientWidth, itemRect.bottom - 1); // ��������� �������������� �����
  708.  
  709. SelectObject(memDC, hOldPen);
  710. DeleteObject(hThinPen);
  711.  
  712. hThinPen = CreatePen(PS_SOLID, 1, RGB(217, 37, 187));
  713. hOldPen = (HPEN)SelectObject(memDC, hThinPen);
  714.  
  715. MoveToEx(memDC, itemRect.right, itemRect.top, NULL);
  716. LineTo(memDC, itemRect.right, itemRect.bottom);
  717.  
  718. SelectObject(memDC, hOldPen);
  719. DeleteObject(hThinPen);
  720. }
  721.  
  722. SelectObject(memDC, hOldPen);
  723. DeleteObject(hThinPen);
  724.  
  725. // 4. �������� ���������� ������ �� �����
  726. BitBlt(hdc, 0, 0, clientRect.right, clientRect.bottom, memDC, 0, 0, SRCCOPY);
  727.  
  728. // 5. ����������� �������
  729. SelectObject(memDC, hOldBitmap);
  730. DeleteObject(hbmMem);
  731. DeleteDC(memDC);
  732.  
  733. if (ps.hdc != nullptr) {
  734. EndPaint(hwnd, &ps);
  735. }
  736. }
  737.  
  738. #define IDT_SINGLE_CLICK_TIMER 0x1
  739. #define IDT_SINGLE_RCLICK_TIMER 0x2
  740.  
  741. #define TIMER_DELAY 150
  742.  
  743. LRESULT CALLBACK Table::CustomListWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
  744. Table* listView = (Table*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  745.  
  746. switch (message)
  747. {
  748. case WM_CREATE:
  749. {
  750. CREATESTRUCT* pCreate = reinterpret_cast<CREATESTRUCT*>(lParam);
  751. Table* pThis = reinterpret_cast<Table*>(pCreate->lpCreateParams);
  752. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
  753. }
  754. break;
  755.  
  756. case WM_DESTROY:
  757. {
  758. KillTimer(hwnd, IDT_SINGLE_CLICK_TIMER);
  759. }
  760. return 0;
  761.  
  762. case WM_SIZE:
  763. {
  764. listView->OnSize();
  765. RECT windowRect;
  766. GetWindowRect(listView->hwndParent, &windowRect);
  767.  
  768. int newWidth = LOWORD(lParam);
  769. int newHeight = HIWORD(lParam);
  770.  
  771. int originalColumnHeight = COLUMN_HEADER_HEIGHT; // Изначальная высота колонок
  772. int originalItemHeight = ITEM_HEIGHT; // Изначальная высота элементов
  773.  
  774. int newColumnHeight = originalColumnHeight * newHeight / SCREEN_HEIGHT;
  775. int newItemHeight = originalItemHeight * newHeight / SCREEN_HEIGHT;
  776.  
  777. listView->GetHeaderClass()->SetColumnHeight(newColumnHeight);
  778. listView->SetItemHeight(newItemHeight + 1);
  779.  
  780. listView->GetHeaderClass()->Resize(newWidth);
  781. }
  782. return 0;
  783.  
  784. case WM_VSCROLL:
  785. {
  786.  
  787. listView->OnVScroll(wParam);
  788. }
  789. return 0;
  790.  
  791. case WM_LBUTTONDOWN:
  792. {
  793. if (!listView->ignoreNextLButtonDown) {
  794. SetTimer(hwnd, IDT_SINGLE_CLICK_TIMER, TIMER_DELAY, NULL);
  795. } else {
  796. listView->ignoreNextLButtonDown = false;
  797. }
  798. }
  799. return 0;
  800.  
  801. case WM_LBUTTONUP:
  802. {
  803. if (!listView->ignoreNextLButtonUp) {
  804. listView->OnLButtonUp(lParam);
  805. }
  806. else {
  807. listView->ignoreNextLButtonUp = false;
  808. }
  809. }
  810. return 0;
  811.  
  812. case WM_LBUTTONDBLCLK:
  813. {
  814. listView->ignoreNextLButtonDown = true;
  815. listView->ignoreNextLButtonUp = true;
  816. KillTimer(hwnd, IDT_SINGLE_CLICK_TIMER);
  817. listView->OnLButtonDblClk(lParam);
  818. }
  819. return 0;
  820.  
  821. case WM_TIMER:
  822. {
  823. if (wParam == IDT_SINGLE_CLICK_TIMER) {
  824. KillTimer(hwnd, IDT_SINGLE_CLICK_TIMER);
  825. if (!listView->ignoreNextLButtonDown) {
  826. POINT point;
  827. GetCursorPos(&point);
  828. ScreenToClient(hwnd, &point);
  829. LPARAM newLParam = MAKELPARAM(point.x, point.y);
  830. listView->OnLButtonDown(newLParam);
  831. }
  832. listView->ignoreNextLButtonDown = false;
  833. }
  834.  
  835. if (wParam == IDT_SINGLE_RCLICK_TIMER) {
  836. KillTimer(hwnd, IDT_SINGLE_RCLICK_TIMER);
  837. if (!listView->ignoreNextRButtonDown) {
  838. POINT point;
  839. GetCursorPos(&point);
  840. ScreenToClient(hwnd, &point);
  841. LPARAM newLParam = MAKELPARAM(point.x, point.y);
  842. listView->OnRButtonDown(newLParam);
  843. }
  844. listView->ignoreNextRButtonDown = false;
  845. }
  846. }
  847. return 0;
  848.  
  849. case WM_RBUTTONDOWN:
  850. {
  851. if (!listView->ignoreNextRButtonDown) {
  852. SetTimer(hwnd, IDT_SINGLE_RCLICK_TIMER, TIMER_DELAY, NULL);
  853. }
  854. else {
  855. listView->ignoreNextRButtonDown = false;
  856. }
  857. }
  858. return 0;
  859.  
  860. case WM_RBUTTONDBLCLK:
  861. {
  862. listView->ignoreNextRButtonDown = true;
  863. listView->ignoreNextRButtonUp = true;
  864. KillTimer(hwnd, IDT_SINGLE_RCLICK_TIMER);
  865. listView->OnRButtonDblClk(lParam);
  866. }
  867. return 0;
  868.  
  869. case WM_RBUTTONUP:
  870. {
  871. if (!listView->ignoreNextRButtonUp) {
  872. //listView->OnRButtonUp(lParam);
  873. }
  874. else {
  875. listView->ignoreNextRButtonUp = false;
  876. }
  877. }
  878. return 0;
  879.  
  880. case WM_MOUSEWHEEL:
  881. {
  882. listView->OnMouseWheel(wParam);
  883. }
  884. return 0;
  885.  
  886. case WM_MOUSEMOVE:
  887. {
  888. listView->OnMouseMove(wParam, lParam);
  889. }
  890. return 0;
  891.  
  892. case WM_ERASEBKGND:
  893. {
  894.  
  895. }
  896. return 1;
  897.  
  898. case WM_SETFONT:
  899. {
  900. listView->OnSetFont(wParam, lParam);
  901. }
  902. break;
  903.  
  904. case WM_PAINT:
  905. {
  906. listView->OnPaint();
  907. }
  908. return 0;
  909.  
  910. default:
  911. return DefWindowProc(hwnd, message, wParam, lParam);
  912. }
  913.  
  914. return 0;
  915. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement