Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <sdkddkver.h>
- // select sdk version to determine common controls functionality
- #undef WINVER
- #define WINVER _WIN32_WINNT_NT4 // that's enough for table control
- #undef _WIN32_WINNT
- #define _WIN32_WINNT WINVER
- #define _WIN32_IE WINVER
- #include <windows.h>
- #include <commctrl.h>
- #include <stdio.h>
- #define CHESSBOARD_ID 3001
- #define MAX_STR_LEN 255
- #define WHITE_CELL_CLR RGB(255, 206, 158)
- #define BLACK_CELL_CLR RGB(209, 139, 71)
- #define FIGURES_FONT_CLR RGB(0, 0, 0)
- #define BACKGROUND_CLR RGB(100, 50, 30)
- #define LETTERS_FONT_CLR RGB(255, 206, 158)
- #define CELL_SIZE 80
- #define CHESSBOARD_COLS 10
- #define CHESSBOARD_ROWS 10
- #define CHESSBOARD_1ST_COL 1 // in grid
- #define CHESSBOARD_1ST_ROW 1 // in grid
- #define CHESSBOARD_LAST_COL 8 // in grid
- #define CHESSBOARD_LAST_ROW 8 // in grid
- #define CHESSBOARD_LEFT_CAPTIONS 0
- #define CHESSBOARD_RIGHT_CAPTIONS (CHESSBOARD_COLS - 1)
- #define CHESSBOARD_TOP_CAPTIONS 0
- #define CHESSBOARD_BOTTOM_CAPTIONS (CHESSBOARD_ROWS - 1)
- typedef enum {EMPTY, BLACK_PAWN, WHITE_PAWN, BLACK_KNIGHT, WHITE_KNIGHT,
- BLACK_BISHOP, WHITE_BISHOP, BLACK_ROOK, WHITE_ROOK, BLACK_QUEEN,
- WHITE_QUEEN, BLACK_KING, WHITE_KING} ChessFigures;
- static LPWSTR CHESS_FIGURES_SMB[] = {L"", L"\u265F", L"\u2659", L"\u265E",
- L"\u2658", L"\u265D", L"\u2657", L"\u265C", L"\u2656", L"\u265B",
- L"\u2655", L"\u265A", L"\u2654"};
- static const INT START_POSITION[8][8] = {
- {BLACK_ROOK, BLACK_KNIGHT, BLACK_BISHOP, BLACK_QUEEN, BLACK_KING,
- BLACK_BISHOP, BLACK_KNIGHT, BLACK_ROOK},
- {BLACK_PAWN, BLACK_PAWN, BLACK_PAWN, BLACK_PAWN, BLACK_PAWN, BLACK_PAWN,
- BLACK_PAWN, BLACK_PAWN},
- {EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY},
- {EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY},
- {EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY},
- {EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY},
- {WHITE_PAWN, WHITE_PAWN, WHITE_PAWN, WHITE_PAWN, WHITE_PAWN, WHITE_PAWN,
- WHITE_PAWN, WHITE_PAWN},
- {WHITE_ROOK, WHITE_KNIGHT, WHITE_BISHOP, WHITE_QUEEN, WHITE_KING,
- WHITE_BISHOP, WHITE_KNIGHT, WHITE_ROOK}};
- static HINSTANCE instance = NULL;
- static HWND mainWin = NULL;
- static HWND chessboard = NULL;
- static HFONT figuresFont = 0;
- static HFONT lettersFont = 0;
- static INT board[8][8] = {{0}};
- HWND CreateMainWindow(VOID);
- LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
- VOID ResizeWindow(HWND hWnd, INT width, INT height);
- SIZE GetWindowSize(HWND hWnd, BOOL internal);
- LRESULT ProcessChessboardDraw(LPARAM lParam);
- VOID InitFonts(VOID);
- VOID ProcessChessboardClick(LPARAM lParam);
- LPWSTR PosToChessNotation(INT col, INT row, LPWSTR out);
- LPWSTR ColToChessNotation(INT col, LPWSTR out);
- LPWSTR RowToChessNotation(INT row, LPWSTR out);
- BOOL IsCellInsideBoard(INT col, INT row);
- HWND CreateStringGrid(HWND parent, INT id, HFONT font);
- VOID StringGridChangeFont(HWND sg, HFONT font);
- VOID StringGridAddCol(HWND sg);
- VOID StringGridAddRow(HWND sg);
- VOID StringGridClear(HWND sg);
- VOID StringGridResize(HWND sg, INT cols, INT rows);
- SIZE StringGridAutoSize(HWND sg, INT rows);
- INT StringGridColCount(HWND sg);
- INT StringGridSetItem(HWND sg, INT col, INT row, LPWSTR text);
- VOID AutoSizeAll(VOID);
- SIZE AutoSizeChessboard(VOID);
- VOID AutoSizeWindow(HWND wnd, SIZE client);
- HWND InitChessBoard(HWND wnd);
- VOID UpdateChessBoard(VOID);
- VOID ResetBoard(VOID);
- VOID UpdateChessBoardCaptions(VOID);
- INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
- LPSTR lpCmdLine, INT nCmdShow) {
- instance = hInstance;
- INITCOMMONCONTROLSEX controls = {sizeof(controls), ICC_LISTVIEW_CLASSES};
- InitCommonControlsEx(&controls);
- mainWin = CreateMainWindow();
- MSG msg;
- while (GetMessage(&msg, NULL, 0, 0)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return (INT)msg.wParam;
- }
- HWND CreateMainWindow(VOID) {
- HWND result = NULL;
- WNDCLASSEX wcx = {0};
- wcx.cbSize = sizeof(wcx);
- wcx.style = CS_HREDRAW | CS_VREDRAW;
- wcx.lpfnWndProc = MainWndProc;
- wcx.cbClsExtra = 0;
- wcx.cbWndExtra = 0;
- wcx.hInstance = instance;
- wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
- wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
- wcx.hbrBackground = GetStockObject(WHITE_BRUSH);
- wcx.lpszMenuName = "MainMenu";
- wcx.lpszClassName = "ChessClass";
- wcx.hIconSm = LoadImage(NULL, MAKEINTRESOURCE(5), IMAGE_ICON,
- GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
- LR_DEFAULTCOLOR);
- if (!RegisterClassEx(&wcx) &&
- (GetLastError() != ERROR_CLASS_ALREADY_EXISTS)) {
- MessageBox(NULL, "Can't register window class", "Error", MB_OK);
- return result;
- }
- result = CreateWindow("ChessClass", "Chess",
- WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
- CW_USEDEFAULT, CW_USEDEFAULT, (HWND)NULL, (HMENU)NULL, instance, NULL);
- if (!result) {
- MessageBox(NULL, "Can't create window", "Error", MB_OK);
- return result;
- }
- return result;
- }
- LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam,
- LPARAM lParam) {
- switch (uMsg) {
- case WM_CREATE:
- mainWin = hWnd;
- chessboard = InitChessBoard(hWnd);
- ResetBoard();
- UpdateChessBoard();
- AutoSizeAll();
- break;
- case WM_CLOSE:
- DestroyWindow(hWnd);
- break;
- case WM_DESTROY:
- if (hWnd == mainWin) {
- PostQuitMessage(0);
- }
- break;
- case WM_NOTIFY:
- switch (LOWORD(wParam)) {
- case CHESSBOARD_ID:
- switch (((LPNMHDR)lParam)->code) {
- case NM_CUSTOMDRAW:
- return ProcessChessboardDraw(lParam);
- break;
- case NM_CLICK:
- ProcessChessboardClick(lParam);
- break;
- }
- break;
- }
- break;
- default:
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
- }
- return 0;
- }
- VOID ResizeWindow(HWND hWnd, INT width, INT height) {
- SetWindowPos(hWnd, 0, 0, 0, width, height,
- SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
- }
- SIZE GetWindowSize(HWND hWnd, BOOL internal) {
- RECT rect = {0};
- if (internal) {
- GetClientRect(hWnd, &rect);
- } else {
- GetWindowRect(hWnd, &rect);
- }
- return (SIZE){rect.right - rect.left, rect.bottom - rect.top};
- }
- LRESULT ProcessChessboardDraw(LPARAM lParam) {
- LRESULT result = CDRF_DODEFAULT;
- LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;
- lplvcd->nmcd.uItemState &= ~(CDIS_FOCUS | CDIS_SELECTED); // hide selection
- INT col = lplvcd->iSubItem;
- INT row = lplvcd->nmcd.dwItemSpec;
- switch (lplvcd->nmcd.dwDrawStage) {
- case CDDS_PREPAINT : // before the paint cycle begins
- // request notifications for individual listview items
- result = CDRF_NOTIFYITEMDRAW;
- break;
- case CDDS_ITEMPREPAINT: // before an item is drawn
- result = CDRF_NOTIFYSUBITEMDRAW;
- break;
- case CDDS_SUBITEM | CDDS_ITEMPREPAINT: // before a subitem is drawn
- if (IsCellInsideBoard(col, row)) { // set board colors
- SelectObject(lplvcd->nmcd.hdc, figuresFont);
- lplvcd->clrText = FIGURES_FONT_CLR;
- lplvcd->clrTextBk = ((col + row) % 2) ?
- BLACK_CELL_CLR : WHITE_CELL_CLR;
- } else { // set background colors
- SelectObject(lplvcd->nmcd.hdc, lettersFont);
- lplvcd->clrTextBk = BACKGROUND_CLR;
- lplvcd->clrText = LETTERS_FONT_CLR;
- }
- result = CDRF_NEWFONT;
- break;
- }
- return result;
- }
- VOID InitFonts(VOID) {
- figuresFont = CreateFont(CELL_SIZE, 0, 0, 0, FW_NORMAL, FALSE, FALSE,
- FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
- CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, "");
- lettersFont = CreateFont(CELL_SIZE, 0, 0, 0, FW_THIN, TRUE, FALSE,
- FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
- CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,
- "Courier New");
- }
- VOID ProcessChessboardClick(LPARAM lParam) {
- LPNMITEMACTIVATE lpnmItem = (LPNMITEMACTIVATE)lParam;
- LVHITTESTINFO hti = {0};
- hti.pt.x = lpnmItem->ptAction.x;
- hti.pt.y = lpnmItem->ptAction.y;
- INT col = lpnmItem->iSubItem;
- INT row = ListView_SubItemHitTest(chessboard, &hti);
- WCHAR cn[] = L"a1";
- if (IsCellInsideBoard(col, row)) {
- MessageBoxW(NULL, PosToChessNotation(col, row, cn), L"Info", MB_OK);
- }
- }
- LPWSTR PosToChessNotation(INT col, INT row, LPWSTR out) {
- WCHAR c[] = L"a";
- ColToChessNotation(col, c);
- WCHAR r[] = L"1";
- RowToChessNotation(row, r);
- swprintf(out, L"%s%s", c, r);
- return out;
- }
- LPWSTR ColToChessNotation(INT col, LPWSTR out) {
- col += 'a' - CHESSBOARD_1ST_COL;
- swprintf(out, L"%c", col);
- return out;
- }
- LPWSTR RowToChessNotation(INT row, LPWSTR out) {
- row = CHESSBOARD_LAST_ROW - row + 1;
- swprintf(out, L"%d", row);
- return out;
- }
- BOOL IsCellInsideBoard(INT col, INT row) {
- return ((col >= CHESSBOARD_1ST_COL) && (col <= CHESSBOARD_LAST_COL) &&
- (row >= CHESSBOARD_1ST_ROW) && (row <= CHESSBOARD_LAST_ROW));
- }
- HWND CreateStringGrid(HWND parent, INT id, HFONT font) {
- HWND result = CreateWindowW(WC_LISTVIEWW, L"",
- WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_REPORT | LVS_NOCOLUMNHEADER,
- CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, parent,
- (HMENU)id, instance, NULL);
- StringGridChangeFont(result, font);
- return result;
- }
- VOID StringGridChangeFont(HWND sg, HFONT font) {
- SendMessageW(sg, WM_SETFONT, (WPARAM)font, (LPARAM)0);
- }
- VOID StringGridAddCol(HWND sg) {
- LVCOLUMNW lvCol = {0};
- lvCol.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM | LVCF_FMT;
- lvCol.fmt = LVCFMT_CENTER; // align text in cell
- lvCol.pszText = NULL;
- lvCol.cx = CELL_SIZE;
- SendMessageW(sg, LVM_INSERTCOLUMNW, 0, (LPARAM)&lvCol);
- }
- VOID StringGridAddRow(HWND sg) {
- static LVITEMW lvItem = {0};
- lvItem.mask = LVIF_TEXT; // text style
- lvItem.cchTextMax = MAX_STR_LEN;
- lvItem.pszText = NULL;
- SendMessageW(sg, LVM_INSERTITEMW, 0, (LPARAM)&lvItem);
- }
- VOID StringGridClear(HWND sg) {
- for (int i = StringGridColCount(sg); i > 0; --i)
- ListView_DeleteColumn(sg, 0);
- ListView_DeleteAllItems(sg);
- }
- VOID StringGridResize(HWND sg, INT cols, INT rows) {
- StringGridClear(sg);
- for (INT i = 0; i < cols; ++i) {
- StringGridAddCol(sg);
- }
- for (INT i = 0; i < rows; ++i) {
- StringGridAddRow(sg);
- }
- }
- SIZE StringGridAutoSize(HWND sg, INT rows) {
- DWORD size = ListView_ApproximateViewRect(sg, -1, -1, rows);
- SIZE result = {0};
- result.cx = LOWORD(size);
- result.cy = HIWORD(size);
- ResizeWindow(sg, result.cx, result.cy);
- return result;
- }
- INT StringGridColCount(HWND sg) {
- return ListView_GetItemCount(sg);
- }
- INT StringGridSetItem(HWND sg, INT col, INT row, LPWSTR text) {
- static LVITEMW lvItem = {0};
- lvItem.mask = LVIF_TEXT; // text style
- lvItem.cchTextMax = MAX_STR_LEN;
- lvItem.pszText = NULL;
- lvItem.iSubItem = col;
- lvItem.iItem = row;
- lvItem.pszText = text;
- SendMessageW(chessboard, LVM_SETITEMW, 0, (LPARAM)&lvItem);
- }
- VOID AutoSizeAll(VOID) {
- SIZE sz = AutoSizeChessboard();
- AutoSizeWindow(mainWin, sz);
- }
- SIZE AutoSizeChessboard(VOID) {
- return StringGridAutoSize(chessboard, CHESSBOARD_ROWS - 1);
- }
- VOID AutoSizeWindow(HWND wnd, SIZE client) {
- SIZE inner = GetWindowSize(wnd, TRUE);
- SIZE outer = GetWindowSize(wnd, FALSE);
- INT borderWidth = outer.cx - inner.cx; // window decorations
- INT borderHeight = outer.cy - inner.cy; // decorations, header, menu
- INT newWidth = client.cx + borderWidth;
- INT newHeight = client.cy + borderHeight;
- ResizeWindow(wnd, newWidth, newHeight);
- }
- HWND InitChessBoard(HWND wnd) {
- InitFonts();
- HWND result = CreateStringGrid(wnd, CHESSBOARD_ID, figuresFont);
- StringGridResize(result, CHESSBOARD_COLS, CHESSBOARD_ROWS);
- return result;
- }
- VOID UpdateChessBoard(VOID) {
- WCHAR buffer[MAX_STR_LEN] = L" ";
- UpdateChessBoardCaptions();
- for (int y = 0; y < 8; ++y) {
- for (int x = 0; x < 8; ++x) {
- StringGridSetItem(chessboard,
- x + CHESSBOARD_1ST_COL, y + CHESSBOARD_1ST_ROW,
- CHESS_FIGURES_SMB[board[y][x]]);
- }
- }
- }
- VOID UpdateChessBoardCaptions(VOID) {
- WCHAR buffer[] = L"a";
- for (INT i = CHESSBOARD_1ST_COL; i < CHESSBOARD_1ST_COL + 8; ++i) {
- ColToChessNotation(i, buffer);
- StringGridSetItem(chessboard, i, CHESSBOARD_TOP_CAPTIONS, buffer);
- StringGridSetItem(chessboard, i, CHESSBOARD_BOTTOM_CAPTIONS, buffer);
- }
- for (INT i = CHESSBOARD_1ST_ROW; i < CHESSBOARD_1ST_ROW + 8; ++i) {
- RowToChessNotation(i, buffer);
- StringGridSetItem(chessboard, CHESSBOARD_LEFT_CAPTIONS, i, buffer);
- StringGridSetItem(chessboard, CHESSBOARD_RIGHT_CAPTIONS, i, buffer);
- }
- }
- VOID ResetBoard(VOID) {
- for (int y = 0; y < 8; ++y) {
- for (int x = 0; x < 8; ++x) {
- board[y][x] = START_POSITION[y][x];
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement