Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <windows.h>
- #include <windowsx.h>
- #include <stdio.h>
- #include <png.h>
- #include <wingdi.h>
- #define IDT_ANIMATION 101
- const wchar_t* menuItems[] = { L"Manage Server", L"Clients", L"Builder", L"About" };
- RECT buttonRects[4];
- HBITMAP buttonBitmaps[4]; // store converted bitmaps
- int selected = 0;
- int hovered = -1;
- // Animation state
- int animating = 0;
- int animRadius = 0;
- POINT animCenter;
- HBITMAP LoadPNGAsHBITMAP(const wchar_t* filename, int* outW, int* outH) {
- FILE* fp = _wfopen(filename, L"rb");
- if (!fp) return NULL;
- // Read PNG signature
- png_byte header[8];
- fread(header, 1, 8, fp);
- if (png_sig_cmp(header, 0, 8)) {
- fclose(fp);
- return NULL;
- }
- png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- if (!png_ptr) { fclose(fp); return NULL; }
- png_infop info_ptr = png_create_info_struct(png_ptr);
- if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); fclose(fp); return NULL; }
- if (setjmp(png_jmpbuf(png_ptr))) {
- png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
- fclose(fp);
- return NULL;
- }
- png_init_io(png_ptr, fp);
- png_set_sig_bytes(png_ptr, 8);
- png_read_info(png_ptr, info_ptr);
- int width = png_get_image_width(png_ptr, info_ptr);
- int height = png_get_image_height(png_ptr, info_ptr);
- png_byte color_type = png_get_color_type(png_ptr, info_ptr);
- png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
- // Force RGBA
- if (bit_depth == 16) png_set_strip_16(png_ptr);
- if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr);
- if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr);
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr);
- if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_PALETTE)
- png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
- if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
- png_set_gray_to_rgb(png_ptr);
- png_read_update_info(png_ptr, info_ptr);
- png_bytep* row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height);
- int rowbytes = png_get_rowbytes(png_ptr, info_ptr);
- unsigned char* image_data = (unsigned char*)malloc(rowbytes * height);
- for (int y = 0; y < height; y++) {
- row_pointers[y] = image_data + y * rowbytes;
- }
- png_read_image(png_ptr, row_pointers);
- fclose(fp);
- png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
- free(row_pointers);
- // Create DIB section
- BITMAPINFO bmi;
- ZeroMemory(&bmi, sizeof(bmi));
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = width;
- bmi.bmiHeader.biHeight = -height; // top-down
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
- void* bits;
- HBITMAP hBitmap = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, &bits, NULL, 0);
- if (!hBitmap) {
- free(image_data);
- return NULL;
- }
- memcpy(bits, image_data, rowbytes * height);
- free(image_data);
- if (outW) *outW = width;
- if (outH) *outH = height;
- return hBitmap;
- }
- LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
- switch (msg) {
- case WM_CREATE: {
- int y = 0;
- for (int i = 0; i < 4; i++) {
- buttonRects[i].left = 0;
- buttonRects[i].top = y;
- buttonRects[i].right = 200; // increased width
- buttonRects[i].bottom = y + 50;
- y += 50;
- }
- int w, h;
- buttonBitmaps[0] = LoadPNGAsHBITMAP(L"manage_server.png", &w, &h);
- buttonBitmaps[1] = LoadPNGAsHBITMAP(L"clients.png", &w, &h);
- buttonBitmaps[2] = LoadPNGAsHBITMAP(L"builder.png", &w, &h);
- buttonBitmaps[3] = LoadPNGAsHBITMAP(L"about.png", &w, &h);
- break;
- }
- case WM_MOUSEMOVE: {
- POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
- int newHover = -1;
- for (int i = 0; i < 4; i++) {
- if (PtInRect(&buttonRects[i], pt)) {
- newHover = i;
- break;
- }
- }
- if (newHover != hovered) {
- hovered = newHover;
- InvalidateRect(hwnd, NULL, TRUE);
- }
- if (hovered != -1)
- SetCursor(LoadCursor(NULL, IDC_HAND));
- else
- SetCursor(LoadCursor(NULL, IDC_ARROW));
- break;
- }
- case WM_LBUTTONDOWN: {
- if (hovered != -1) {
- selected = hovered;
- animCenter.x = GET_X_LPARAM(lParam); // X where clicked
- animCenter.y = GET_Y_LPARAM(lParam); // Y where clicked
- animRadius = 0;
- animating = 1;
- SetTimer(hwnd, IDT_ANIMATION, 10, NULL);
- InvalidateRect(hwnd, NULL, TRUE);
- }
- break;
- }
- case WM_TIMER: {
- if (wParam == IDT_ANIMATION) {
- animRadius += 15;
- if (animRadius > 200) {
- KillTimer(hwnd, IDT_ANIMATION);
- animating = 0;
- }
- InvalidateRect(hwnd, NULL, TRUE);
- }
- break;
- }
- case WM_PAINT: {
- PAINTSTRUCT ps;
- HDC hdc = BeginPaint(hwnd, &ps);
- HDC memDC = CreateCompatibleDC(hdc);
- RECT clientRect;
- GetClientRect(hwnd, &clientRect);
- HBITMAP memBitmap = CreateCompatibleBitmap(hdc, clientRect.right, clientRect.bottom);
- HBITMAP oldBitmap = (HBITMAP)SelectObject(memDC, memBitmap);
- HBRUSH sidebarBrush = CreateSolidBrush(RGB(40, 44, 52));
- FillRect(memDC, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
- RECT sidebar = { 0, 0, 200, ps.rcPaint.bottom }; // match new button width
- FillRect(memDC, &sidebar, sidebarBrush);
- DeleteObject(sidebarBrush);
- for (int i = 0; i < 4; i++) {
- HBRUSH brush;
- if (i == selected)
- brush = CreateSolidBrush(RGB(0, 122, 204));
- else if (i == hovered)
- brush = CreateSolidBrush(RGB(60, 64, 72));
- else
- brush = CreateSolidBrush(RGB(40, 44, 52));
- FillRect(memDC, &buttonRects[i], brush);
- DeleteObject(brush);
- }
- if (animating) {
- HBRUSH animBrush = CreateSolidBrush(RGB(0, 150, 255));
- HBRUSH oldBrush = (HBRUSH)SelectObject(memDC, animBrush);
- HPEN animPen = CreatePen(PS_NULL, 0, 0);
- HPEN oldPen = (HPEN)SelectObject(memDC, animPen);
- HRGN rgn = CreateRectRgnIndirect(&buttonRects[selected]);
- SelectClipRgn(memDC, rgn);
- DeleteObject(rgn);
- Ellipse(memDC,
- animCenter.x - animRadius,
- animCenter.y - animRadius,
- animCenter.x + animRadius,
- animCenter.y + animRadius);
- SelectClipRgn(memDC, NULL);
- SelectObject(memDC, oldBrush);
- DeleteObject(animBrush);
- SelectObject(memDC, oldPen);
- DeleteObject(animPen);
- }
- LOGFONT lf = { 0 };
- lf.lfHeight = 18;
- lf.lfWeight = FW_BOLD;
- wcscpy(lf.lfFaceName, L"Segoe UI");
- HFONT hFont = CreateFontIndirect(&lf);
- HFONT oldFont = (HFONT)SelectObject(memDC, hFont);
- for (int i = 0; i < 4; i++) {
- if (buttonBitmaps[i]) {
- HDC iconDC = CreateCompatibleDC(memDC);
- HBITMAP oldBmp = (HBITMAP)SelectObject(iconDC, buttonBitmaps[i]);
- BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
- int iconX = buttonRects[i].left + 10;
- int iconY = buttonRects[i].top + (buttonRects[i].bottom - buttonRects[i].top - 32) / 2;
- AlphaBlend(memDC, iconX, iconY, 32, 32, iconDC, 0, 0, 32, 32, bf);
- SelectObject(iconDC, oldBmp);
- DeleteDC(iconDC);
- }
- RECT textRect = buttonRects[i];
- textRect.left += 60; // more space after 32x32 PNG
- SetBkMode(memDC, TRANSPARENT);
- SetTextColor(memDC, RGB(255, 255, 255));
- DrawTextW(memDC, menuItems[i], -1, &textRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
- }
- RECT content = { 210, 50, ps.rcPaint.right, ps.rcPaint.bottom };
- const wchar_t* contentText[] = {
- L"🖥 Manage your Server here.",
- L"👥 View your Clients.",
- L"🔨 Build your Tools here.",
- L"ℹ About this Application."
- };
- SetBkMode(memDC, OPAQUE);
- SetBkColor(memDC, GetSysColor(COLOR_WINDOW));
- SetTextColor(memDC, GetSysColor(COLOR_WINDOWTEXT));
- DrawTextW(memDC, contentText[selected], -1, &content, DT_LEFT | DT_TOP);
- BitBlt(hdc, 0, 0, clientRect.right, clientRect.bottom, memDC, 0, 0, SRCCOPY);
- SelectObject(memDC, oldBitmap);
- DeleteObject(memBitmap);
- DeleteDC(memDC);
- SelectObject(memDC, oldFont);
- DeleteObject(hFont);
- EndPaint(hwnd, &ps);
- break;
- }
- case WM_DESTROY:
- KillTimer(hwnd, IDT_ANIMATION);
- for (int i = 0; i < 4; i++) {
- if (buttonBitmaps[i]) DeleteObject(buttonBitmaps[i]);
- }
- PostQuitMessage(0);
- break;
- }
- return DefWindowProc(hwnd, msg, wParam, lParam);
- }
- int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
- const wchar_t CLASS_NAME[] = L"SidebarWin32";
- WNDCLASS wc = { 0 };
- wc.lpfnWndProc = WndProc;
- wc.hInstance = hInstance;
- wc.lpszClassName = CLASS_NAME;
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);
- RegisterClass(&wc);
- HWND hwnd = CreateWindowEx(
- 0, CLASS_NAME, L"Win32 Sidebar Navigation",
- WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
- NULL, NULL, hInstance, NULL
- );
- ShowWindow(hwnd, nCmdShow);
- MSG msg;
- while (GetMessage(&msg, NULL, 0, 0)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment