pureclover1

SIdebar_win32.c

Sep 18th, 2025
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.25 KB | Source Code | 0 0
  1. #include <windows.h>
  2. #include <windowsx.h>
  3. #include <stdio.h>
  4. #include <png.h>
  5. #include <wingdi.h>
  6.  
  7. #define IDT_ANIMATION 101
  8.  
  9. const wchar_t* menuItems[] = { L"Manage Server", L"Clients", L"Builder", L"About" };
  10. RECT buttonRects[4];
  11. HBITMAP buttonBitmaps[4];  // store converted bitmaps
  12. int selected = 0;
  13. int hovered = -1;
  14.  
  15. // Animation state
  16. int animating = 0;
  17. int animRadius = 0;
  18. POINT animCenter;
  19.  
  20. HBITMAP LoadPNGAsHBITMAP(const wchar_t* filename, int* outW, int* outH) {
  21.     FILE* fp = _wfopen(filename, L"rb");
  22.     if (!fp) return NULL;
  23.  
  24.     // Read PNG signature
  25.     png_byte header[8];
  26.     fread(header, 1, 8, fp);
  27.     if (png_sig_cmp(header, 0, 8)) {
  28.         fclose(fp);
  29.         return NULL;
  30.     }
  31.  
  32.     png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  33.     if (!png_ptr) { fclose(fp); return NULL; }
  34.  
  35.     png_infop info_ptr = png_create_info_struct(png_ptr);
  36.     if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); fclose(fp); return NULL; }
  37.  
  38.     if (setjmp(png_jmpbuf(png_ptr))) {
  39.         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
  40.         fclose(fp);
  41.         return NULL;
  42.     }
  43.  
  44.     png_init_io(png_ptr, fp);
  45.     png_set_sig_bytes(png_ptr, 8);
  46.  
  47.     png_read_info(png_ptr, info_ptr);
  48.  
  49.     int width = png_get_image_width(png_ptr, info_ptr);
  50.     int height = png_get_image_height(png_ptr, info_ptr);
  51.     png_byte color_type = png_get_color_type(png_ptr, info_ptr);
  52.     png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
  53.  
  54.     // Force RGBA
  55.     if (bit_depth == 16) png_set_strip_16(png_ptr);
  56.     if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr);
  57.     if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr);
  58.     if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr);
  59.     if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_PALETTE)
  60.         png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
  61.     if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  62.         png_set_gray_to_rgb(png_ptr);
  63.  
  64.     png_read_update_info(png_ptr, info_ptr);
  65.  
  66.     png_bytep* row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height);
  67.     int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
  68.     unsigned char* image_data = (unsigned char*)malloc(rowbytes * height);
  69.  
  70.     for (int y = 0; y < height; y++) {
  71.         row_pointers[y] = image_data + y * rowbytes;
  72.     }
  73.  
  74.     png_read_image(png_ptr, row_pointers);
  75.  
  76.     fclose(fp);
  77.     png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
  78.     free(row_pointers);
  79.  
  80.     // Create DIB section
  81.     BITMAPINFO bmi;
  82.     ZeroMemory(&bmi, sizeof(bmi));
  83.     bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  84.     bmi.bmiHeader.biWidth = width;
  85.     bmi.bmiHeader.biHeight = -height; // top-down
  86.     bmi.bmiHeader.biPlanes = 1;
  87.     bmi.bmiHeader.biBitCount = 32;
  88.     bmi.bmiHeader.biCompression = BI_RGB;
  89.  
  90.     void* bits;
  91.     HBITMAP hBitmap = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, &bits, NULL, 0);
  92.     if (!hBitmap) {
  93.         free(image_data);
  94.         return NULL;
  95.     }
  96.  
  97.     memcpy(bits, image_data, rowbytes * height);
  98.     free(image_data);
  99.  
  100.     if (outW) *outW = width;
  101.     if (outH) *outH = height;
  102.     return hBitmap;
  103. }
  104.  
  105. LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
  106.     switch (msg) {
  107.     case WM_CREATE: {
  108.         int y = 0;
  109.         for (int i = 0; i < 4; i++) {
  110.             buttonRects[i].left = 0;
  111.             buttonRects[i].top = y;
  112.             buttonRects[i].right = 200;   // increased width
  113.             buttonRects[i].bottom = y + 50;
  114.             y += 50;
  115.         }
  116.  
  117.         int w, h;
  118.         buttonBitmaps[0] = LoadPNGAsHBITMAP(L"manage_server.png", &w, &h);
  119.         buttonBitmaps[1] = LoadPNGAsHBITMAP(L"clients.png", &w, &h);
  120.         buttonBitmaps[2] = LoadPNGAsHBITMAP(L"builder.png", &w, &h);
  121.         buttonBitmaps[3] = LoadPNGAsHBITMAP(L"about.png", &w, &h);
  122.  
  123.         break;
  124.     }
  125.  
  126.     case WM_MOUSEMOVE: {
  127.         POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
  128.         int newHover = -1;
  129.         for (int i = 0; i < 4; i++) {
  130.             if (PtInRect(&buttonRects[i], pt)) {
  131.                 newHover = i;
  132.                 break;
  133.             }
  134.         }
  135.         if (newHover != hovered) {
  136.             hovered = newHover;
  137.             InvalidateRect(hwnd, NULL, TRUE);
  138.         }
  139.         if (hovered != -1)
  140.             SetCursor(LoadCursor(NULL, IDC_HAND));
  141.         else
  142.             SetCursor(LoadCursor(NULL, IDC_ARROW));
  143.         break;
  144.     }
  145.  
  146.     case WM_LBUTTONDOWN: {
  147.         if (hovered != -1) {
  148.             selected = hovered;
  149.             animCenter.x = GET_X_LPARAM(lParam); // X where clicked
  150.             animCenter.y = GET_Y_LPARAM(lParam); // Y where clicked
  151.             animRadius = 0;
  152.             animating = 1;
  153.             SetTimer(hwnd, IDT_ANIMATION, 10, NULL);
  154.             InvalidateRect(hwnd, NULL, TRUE);
  155.         }
  156.         break;
  157.     }
  158.  
  159.  
  160.     case WM_TIMER: {
  161.         if (wParam == IDT_ANIMATION) {
  162.             animRadius += 15;
  163.             if (animRadius > 200) {
  164.                 KillTimer(hwnd, IDT_ANIMATION);
  165.                 animating = 0;
  166.             }
  167.             InvalidateRect(hwnd, NULL, TRUE);
  168.         }
  169.         break;
  170.     }
  171.  
  172.     case WM_PAINT: {
  173.         PAINTSTRUCT ps;
  174.         HDC hdc = BeginPaint(hwnd, &ps);
  175.  
  176.         HDC memDC = CreateCompatibleDC(hdc);
  177.         RECT clientRect;
  178.         GetClientRect(hwnd, &clientRect);
  179.         HBITMAP memBitmap = CreateCompatibleBitmap(hdc, clientRect.right, clientRect.bottom);
  180.         HBITMAP oldBitmap = (HBITMAP)SelectObject(memDC, memBitmap);
  181.  
  182.         HBRUSH sidebarBrush = CreateSolidBrush(RGB(40, 44, 52));
  183.         FillRect(memDC, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
  184.         RECT sidebar = { 0, 0, 200, ps.rcPaint.bottom }; // match new button width
  185.         FillRect(memDC, &sidebar, sidebarBrush);
  186.         DeleteObject(sidebarBrush);
  187.  
  188.         for (int i = 0; i < 4; i++) {
  189.             HBRUSH brush;
  190.             if (i == selected)
  191.                 brush = CreateSolidBrush(RGB(0, 122, 204));
  192.             else if (i == hovered)
  193.                 brush = CreateSolidBrush(RGB(60, 64, 72));
  194.             else
  195.                 brush = CreateSolidBrush(RGB(40, 44, 52));
  196.  
  197.             FillRect(memDC, &buttonRects[i], brush);
  198.             DeleteObject(brush);
  199.         }
  200.  
  201.         if (animating) {
  202.             HBRUSH animBrush = CreateSolidBrush(RGB(0, 150, 255));
  203.             HBRUSH oldBrush = (HBRUSH)SelectObject(memDC, animBrush);
  204.             HPEN animPen = CreatePen(PS_NULL, 0, 0);
  205.             HPEN oldPen = (HPEN)SelectObject(memDC, animPen);
  206.  
  207.             HRGN rgn = CreateRectRgnIndirect(&buttonRects[selected]);
  208.             SelectClipRgn(memDC, rgn);
  209.             DeleteObject(rgn);
  210.  
  211.             Ellipse(memDC,
  212.                 animCenter.x - animRadius,
  213.                 animCenter.y - animRadius,
  214.                 animCenter.x + animRadius,
  215.                 animCenter.y + animRadius);
  216.  
  217.             SelectClipRgn(memDC, NULL);
  218.             SelectObject(memDC, oldBrush);
  219.             DeleteObject(animBrush);
  220.             SelectObject(memDC, oldPen);
  221.             DeleteObject(animPen);
  222.         }
  223.  
  224.         LOGFONT lf = { 0 };
  225.         lf.lfHeight = 18;
  226.         lf.lfWeight = FW_BOLD;
  227.         wcscpy(lf.lfFaceName, L"Segoe UI");
  228.         HFONT hFont = CreateFontIndirect(&lf);
  229.         HFONT oldFont = (HFONT)SelectObject(memDC, hFont);
  230.  
  231.         for (int i = 0; i < 4; i++) {
  232.             if (buttonBitmaps[i]) {
  233.                 HDC iconDC = CreateCompatibleDC(memDC);
  234.                 HBITMAP oldBmp = (HBITMAP)SelectObject(iconDC, buttonBitmaps[i]);
  235.  
  236.                 BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
  237.                 int iconX = buttonRects[i].left + 10;
  238.                 int iconY = buttonRects[i].top + (buttonRects[i].bottom - buttonRects[i].top - 32) / 2;
  239.                 AlphaBlend(memDC, iconX, iconY, 32, 32, iconDC, 0, 0, 32, 32, bf);
  240.  
  241.                 SelectObject(iconDC, oldBmp);
  242.                 DeleteDC(iconDC);
  243.             }
  244.  
  245.             RECT textRect = buttonRects[i];
  246.             textRect.left += 60; // more space after 32x32 PNG
  247.             SetBkMode(memDC, TRANSPARENT);
  248.             SetTextColor(memDC, RGB(255, 255, 255));
  249.             DrawTextW(memDC, menuItems[i], -1, &textRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
  250.         }
  251.  
  252.         RECT content = { 210, 50, ps.rcPaint.right, ps.rcPaint.bottom };
  253.         const wchar_t* contentText[] = {
  254.             L"🖥 Manage your Server here.",
  255.             L"👥 View your Clients.",
  256.             L"🔨 Build your Tools here.",
  257.             L"ℹ About this Application."
  258.         };
  259.         SetBkMode(memDC, OPAQUE);
  260.         SetBkColor(memDC, GetSysColor(COLOR_WINDOW));
  261.         SetTextColor(memDC, GetSysColor(COLOR_WINDOWTEXT));
  262.         DrawTextW(memDC, contentText[selected], -1, &content, DT_LEFT | DT_TOP);
  263.  
  264.         BitBlt(hdc, 0, 0, clientRect.right, clientRect.bottom, memDC, 0, 0, SRCCOPY);
  265.  
  266.         SelectObject(memDC, oldBitmap);
  267.         DeleteObject(memBitmap);
  268.         DeleteDC(memDC);
  269.         SelectObject(memDC, oldFont);
  270.         DeleteObject(hFont);
  271.  
  272.         EndPaint(hwnd, &ps);
  273.         break;
  274.     }
  275.  
  276.     case WM_DESTROY:
  277.         KillTimer(hwnd, IDT_ANIMATION);
  278.         for (int i = 0; i < 4; i++) {
  279.             if (buttonBitmaps[i]) DeleteObject(buttonBitmaps[i]);
  280.         }
  281.         PostQuitMessage(0);
  282.         break;
  283.     }
  284.     return DefWindowProc(hwnd, msg, wParam, lParam);
  285. }
  286.  
  287. int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
  288.     const wchar_t CLASS_NAME[] = L"SidebarWin32";
  289.  
  290.     WNDCLASS wc = { 0 };
  291.     wc.lpfnWndProc = WndProc;
  292.     wc.hInstance = hInstance;
  293.     wc.lpszClassName = CLASS_NAME;
  294.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  295.  
  296.     RegisterClass(&wc);
  297.  
  298.     HWND hwnd = CreateWindowEx(
  299.         0, CLASS_NAME, L"Win32 Sidebar Navigation",
  300.         WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
  301.         NULL, NULL, hInstance, NULL
  302.     );
  303.  
  304.     ShowWindow(hwnd, nCmdShow);
  305.  
  306.     MSG msg;
  307.     while (GetMessage(&msg, NULL, 0, 0)) {
  308.         TranslateMessage(&msg);
  309.         DispatchMessage(&msg);
  310.     }
  311.     return 0;
  312. }
  313.  
Advertisement
Add Comment
Please, Sign In to add comment