Advertisement
j3628800

Messages Prev/Next/Latest

May 2nd, 2024
243
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C (WinAPI) 7.59 KB | Source Code | 0 0
  1. /**
  2.  * An old "scroll-able log" I made when I first learnt Windows programming.
  3.  * Very basic and not really useful, but took me a long time to figure out
  4.  * the auto size expansion, dynamic memory management, syncing, wide string stuff,
  5.  * and so on, so want to keep it somewhere.
  6.  *
  7.  * Combined dsm-log.c and dsm-log.rc to save space and reduce contex switching
  8.  */
  9.  
  10. #include <windows.h>
  11. #include <stdio.h>
  12.  
  13. #ifndef UNICODE
  14. #define UNICODE
  15. #endif
  16.  
  17. #define N_SHOWN 1    /* how many messages to show at the same time */
  18. #define S_TEST L"[Hit Test a few times]"
  19. #define CLASS_LOGSCROLLABLE L"LogScrollable"
  20. #define MAX_LEN_MSG 32
  21.  
  22. void *Zalloc(size_t len) {
  23.     void *p = malloc(len);
  24.     if (p==NULL) {
  25.         perror("Error calling malloc()\n");
  26.     }
  27.     return(p);
  28. }
  29. void KlasWOld(HWND hWnd, CHAR *snle, size_t lenSnle) {
  30.     WCHAR *sZof = Zalloc((lenSnle+1)*sizeof(WCHAR));
  31.     MultiByteToWideChar(CP_UTF8, 0, snle, lenSnle, sZof, lenSnle);
  32.     sZof[lenSnle] = '\0';
  33.     SetWindowTextW(hWnd, sZof);
  34.     free(sZof);
  35. }
  36. void KlasW(HWND hTarget, LPWSTR sMsg) {
  37.     SetWindowTextW(hTarget, sMsg);
  38. }
  39.  
  40.  
  41. enum tag_TEST_ID {
  42.     IDB_TEST_ADD_MSG = 101, IDB_TEST_CLEAR, IDB_TEST_EXIT
  43. };
  44. enum tag_LS_ID {
  45.     IDB_PREV = 190, IDB_NEXT = 191, IDB_LAST = 192
  46. };
  47. enum tag_TAQ {
  48.     L_WIDTH = 40, L_HEIGHT = 20, L_TEXT = 200,
  49.     LS_X_CONTROLS = 10, LS_Y_CONTROL_TOP = 10 + N_SHOWN * L_HEIGHT,
  50.     LS_X_MSGS = 10 + L_WIDTH, LS_Y_MSG_TOP = 10 + L_HEIGHT
  51. };
  52.  
  53.  
  54. /* -- tyeps -- */
  55. typedef struct tag_LOGSCROLLABLE {
  56.     HWND hCurrent;
  57.     HWND hCurIndex;
  58.     HWND hButtonPrev;
  59.     HWND hButtonNext;
  60.     int index;
  61.     BOOL isAutoScroll;    /* auto-scroll on/of */
  62.     int capMsgs;    /* capacity */
  63.     int nMsgs;
  64.     LPWSTR *listMsgs;
  65. } LOGSCROLLABLE, *PLOGSCROLLABLE;
  66.  
  67.  
  68. void LS_Init(PLOGSCROLLABLE logData) {
  69.     logData->capMsgs = 8;
  70.     logData->index = 0;
  71.     logData->isAutoScroll = TRUE;
  72.     logData->nMsgs = 0;
  73.     logData->listMsgs = (LPWSTR *) Zalloc((logData->capMsgs)*sizeof(LPVOID));
  74.     printf("<LS I.> init'd\n");
  75. }
  76. void LS_Expand(PLOGSCROLLABLE logData) {
  77.     printf("<LS E.> attempting to expand capacity...\n");
  78.     int newCapMsgs = 3 * (logData->capMsgs) / 2;
  79.     logData->listMsgs = (LPWSTR *) realloc(logData->listMsgs, newCapMsgs*sizeof(LPVOID));
  80.     if (logData->listMsgs==NULL) { perror("realloc() failed\n"); }
  81.     logData->capMsgs = newCapMsgs;
  82.     printf("<LS E.> expanded capacity to %d\n", newCapMsgs);
  83. }
  84.  
  85.  
  86. void LS_CreateWindows(PLOGSCROLLABLE logData, HWND hWnd) {
  87.     HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr(hWnd, GWLP_HINSTANCE);
  88.     logData->hCurrent = CreateWindowW(L"Static", S_TEST, WS_CHILD | WS_VISIBLE,
  89.         LS_X_MSGS, LS_Y_MSG_TOP, L_TEXT, L_HEIGHT,
  90.         hWnd, NULL, hInst, NULL);
  91.     logData->hButtonPrev = CreateWindowW(L"Button", L"Prev", WS_CHILD | WS_VISIBLE,
  92.         LS_X_CONTROLS, LS_Y_CONTROL_TOP+0*L_HEIGHT, L_WIDTH, L_HEIGHT,
  93.         hWnd, (HMENU) IDB_PREV, hInst, NULL);
  94.     logData->hCurIndex = CreateWindowW(L"Static", L"#", WS_CHILD | WS_VISIBLE,
  95.         LS_X_CONTROLS, LS_Y_CONTROL_TOP+1*L_HEIGHT, L_WIDTH, L_HEIGHT,
  96.         hWnd, NULL, hInst, NULL);
  97.     logData->hButtonNext = CreateWindowW(L"Button", L"Next", WS_CHILD | WS_VISIBLE,
  98.         LS_X_CONTROLS, LS_Y_CONTROL_TOP+2*L_HEIGHT, L_WIDTH, L_HEIGHT,
  99.         hWnd, (HMENU) IDB_NEXT, hInst, NULL);
  100.     CreateWindowW(L"Button", L"Latest", WS_CHILD | WS_VISIBLE,
  101.         LS_X_CONTROLS, LS_Y_CONTROL_TOP+3*L_HEIGHT, L_WIDTH, L_HEIGHT,
  102.         hWnd, (HMENU) IDB_LAST, hInst, NULL);
  103.     CreateWindowW(L"Button", L"exit", WS_CHILD | WS_VISIBLE,
  104.         240, 0, 40, 20, hWnd, (HMENU) IDB_TEST_EXIT, NULL, NULL);
  105.     CreateWindowW(L"Button", L"test", WS_CHILD | WS_VISIBLE,
  106.         240, 20, 40, 20, hWnd, (HMENU) IDB_TEST_ADD_MSG, NULL, NULL);
  107.     printf("<LS C.W.> created windows\n");
  108. }
  109.  
  110. void LS_Scroll(PLOGSCROLLABLE logData, WPARAM wParam) {
  111.     if (logData->nMsgs==0) {
  112.         return;
  113.     }
  114.  
  115.     switch (wParam) {
  116.     case IDB_PREV:
  117.         logData->isAutoScroll = FALSE;    /* auto-scroll off */
  118.         logData->index--;
  119.         break;
  120.     case IDB_NEXT:
  121.         logData->index++;
  122.         break;
  123.     case IDB_LAST:
  124.         logData->isAutoScroll = TRUE;    /* auto-scroll on */
  125.         logData->index = logData->nMsgs - 1;
  126.         break;
  127.     default:
  128.         /* need this to manually update sIndex */
  129.         break;
  130.     }
  131.    
  132.     if ((logData->index) < 0) {
  133.         MessageBeep(MB_ICONWARNING);
  134.         logData->index = 0;
  135.     }
  136.     if ((logData->index) > (logData->nMsgs)-1) {
  137.         MessageBeep(MB_ICONWARNING);
  138.         logData->index = logData->nMsgs - 1;
  139.     }
  140.  
  141.     LPWSTR sIndex = (LPWSTR) Zalloc(10*sizeof(LPVOID));
  142.     wsprintfW(sIndex, L"%d/%d", logData->index+1, logData->nMsgs);
  143.     KlasW(logData->hCurIndex, sIndex);
  144.     KlasW(logData->hCurrent, logData->listMsgs[logData->index]);
  145.     free(sIndex);
  146. }
  147.  
  148. void LS_AddMsg(PLOGSCROLLABLE logData, LPWSTR sMsg) {
  149.     /* we need vwsprintf, right prlxvalue? */
  150.     LPWSTR sMsgInList = (LPWSTR) Zalloc(MAX_LEN_MSG*sizeof(WCHAR));
  151.     wcsncpy(sMsgInList, sMsg, MAX_LEN_MSG);
  152.     sMsgInList[0] = (SHORT) (logData->nMsgs + 'B');
  153.     /* too lazy to generate actually plausible messages */
  154.     sMsgInList[MAX_LEN_MSG-1] = L'\0';
  155.  
  156.     logData->listMsgs[logData->nMsgs] = sMsgInList;
  157.     logData->nMsgs++;
  158.  
  159.     LS_Scroll(logData, (WPARAM) 0);    /* set new text */
  160.     if (logData->isAutoScroll) {
  161.         logData->index++;
  162.     }
  163.  
  164.     if ((logData->nMsgs) > (logData->capMsgs - 5)) {
  165.         LS_Expand(logData);
  166.     }
  167.  
  168.     //for (int i=0; i<logData->nMsgs; i++) {
  169.     //wprintf(L"%p is %s\n", logData->listMsgs[i], logData->listMsgs[i]);
  170.     //}
  171.  
  172. }
  173. void LS_Cleanup(PLOGSCROLLABLE logData) {
  174.     for (int i=0; i<logData->nMsgs; i++) {
  175.         if (logData->listMsgs[i]) {
  176.             free(logData->listMsgs[i]);
  177.         }
  178.     }
  179.     free(logData->listMsgs);
  180.     free(logData);
  181.     printf("<LS C.> Cleanup done!\n");
  182. }
  183.  
  184. void LS_ButtonControl(PLOGSCROLLABLE logData, HWND hWnd, WPARAM wParam) {
  185.     switch (wParam) {
  186.     case IDB_PREV:
  187.     case IDB_NEXT:
  188.     case IDB_LAST:
  189.         LS_Scroll(logData, wParam);
  190.         break;
  191.     case IDB_TEST_EXIT:
  192.         SendMessageW(hWnd, WM_DESTROY, (WPARAM) NULL, (LPARAM) NULL);
  193.         break;
  194.     case IDB_TEST_ADD_MSG:
  195.         LS_AddMsg(logData, L"*ary says hi");
  196.         break;
  197.     }
  198. }
  199. LRESULT CALLBACK WndProc(HWND hWnd, UINT wmsg, WPARAM wParam, LPARAM lParam) {
  200.     static PLOGSCROLLABLE logData = NULL;
  201.  
  202.     switch (wmsg) {
  203.     case WM_CREATE:
  204.         logData = (PLOGSCROLLABLE) Zalloc(sizeof(LOGSCROLLABLE));
  205.         LS_Init(logData);
  206.         LS_CreateWindows(logData, hWnd);
  207.         break;
  208.     case WM_COMMAND:
  209.         LS_ButtonControl(logData, hWnd, wParam);
  210.         break;
  211.     case WM_ERASEBKGND:
  212.         break;    /* allegd fix for flashing */
  213.     case WM_DESTROY:
  214.         LS_Cleanup(logData);
  215.         PostQuitMessage(0);
  216.         break;
  217.     }
  218.     return(DefWindowProcW(hWnd, wmsg, wParam, lParam));
  219. }
  220. int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine, int nCmdShow) {
  221.     WNDCLASSW wc = {0};
  222.     wc.lpfnWndProc = WndProc;
  223.     wc.hInstance = hInst;
  224.     wc.lpszClassName = CLASS_LOGSCROLLABLE;
  225.     RegisterClassW(&wc);
  226.     HWND hWnd;    /* "HWND hWnd;" indeed */
  227.     hWnd = CreateWindowW(CLASS_LOGSCROLLABLE, L"Log", WS_OVERLAPPEDWINDOW,
  228.         CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, NULL, NULL, hInst, NULL);
  229.     ShowWindow(hWnd, nCmdShow);
  230.     MSG windowMsg = {0};
  231.     while (GetMessage(&windowMsg, NULL, 0, 0)) {
  232.         TranslateMessage(&windowMsg);
  233.         DispatchMessage(&windowMsg);
  234.     }
  235.     return(0);
  236. }
  237.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement