sizetip.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * sizetip.c - resize tips for PuTTY(tel) terminal window.
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <tchar.h>
  7. #include "putty.h"
  8. static ATOM tip_class = 0;
  9. static HFONT tip_font;
  10. static COLORREF tip_bg;
  11. static COLORREF tip_text;
  12. static LRESULT CALLBACK SizeTipWndProc(HWND hWnd, UINT nMsg,
  13. WPARAM wParam, LPARAM lParam)
  14. {
  15. switch (nMsg) {
  16. case WM_ERASEBKGND:
  17. return true;
  18. case WM_PAINT: {
  19. HBRUSH hbr;
  20. HGDIOBJ holdbr;
  21. RECT cr;
  22. int wtlen;
  23. LPTSTR wt;
  24. HDC hdc;
  25. PAINTSTRUCT ps;
  26. hdc = BeginPaint(hWnd, &ps);
  27. SelectObject(hdc, tip_font);
  28. SelectObject(hdc, GetStockObject(BLACK_PEN));
  29. hbr = CreateSolidBrush(tip_bg);
  30. holdbr = SelectObject(hdc, hbr);
  31. GetClientRect(hWnd, &cr);
  32. Rectangle(hdc, cr.left, cr.top, cr.right, cr.bottom);
  33. wtlen = GetWindowTextLength(hWnd);
  34. wt = (LPTSTR) snewn(wtlen + 1, TCHAR);
  35. GetWindowText(hWnd, wt, wtlen + 1);
  36. SetTextColor(hdc, tip_text);
  37. SetBkColor(hdc, tip_bg);
  38. TextOut(hdc, cr.left + 3, cr.top + 3, wt, wtlen);
  39. sfree(wt);
  40. SelectObject(hdc, holdbr);
  41. DeleteObject(hbr);
  42. EndPaint(hWnd, &ps);
  43. return 0;
  44. }
  45. case WM_NCHITTEST:
  46. return HTTRANSPARENT;
  47. case WM_DESTROY:
  48. DeleteObject(tip_font);
  49. tip_font = NULL;
  50. break;
  51. case WM_SETTEXT: {
  52. LPCTSTR str = (LPCTSTR) lParam;
  53. SIZE sz;
  54. HDC hdc = CreateCompatibleDC(NULL);
  55. SelectObject(hdc, tip_font);
  56. GetTextExtentPoint32(hdc, str, _tcslen(str), &sz);
  57. SetWindowPos(hWnd, NULL, 0, 0, sz.cx + 6, sz.cy + 6,
  58. SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
  59. InvalidateRect(hWnd, NULL, false);
  60. DeleteDC(hdc);
  61. break;
  62. }
  63. }
  64. return DefWindowProc(hWnd, nMsg, wParam, lParam);
  65. }
  66. static HWND tip_wnd = NULL;
  67. static bool tip_enabled = false;
  68. void UpdateSizeTip(HWND src, int cx, int cy)
  69. {
  70. TCHAR str[32];
  71. if (!tip_enabled)
  72. return;
  73. if (!tip_wnd) {
  74. NONCLIENTMETRICS nci;
  75. /* First make sure the window class is registered */
  76. if (!tip_class) {
  77. WNDCLASS wc;
  78. wc.style = CS_HREDRAW | CS_VREDRAW;
  79. wc.lpfnWndProc = SizeTipWndProc;
  80. wc.cbClsExtra = 0;
  81. wc.cbWndExtra = 0;
  82. wc.hInstance = hinst;
  83. wc.hIcon = NULL;
  84. wc.hCursor = NULL;
  85. wc.hbrBackground = NULL;
  86. wc.lpszMenuName = NULL;
  87. wc.lpszClassName = "SizeTipClass";
  88. tip_class = RegisterClass(&wc);
  89. }
  90. #if 0
  91. /* Default values based on Windows Standard color scheme */
  92. tip_font = GetStockObject(SYSTEM_FONT);
  93. tip_bg = RGB(255, 255, 225);
  94. tip_text = RGB(0, 0, 0);
  95. #endif
  96. /* Prepare other GDI objects and drawing info */
  97. tip_bg = GetSysColor(COLOR_INFOBK);
  98. tip_text = GetSysColor(COLOR_INFOTEXT);
  99. memset(&nci, 0, sizeof(NONCLIENTMETRICS));
  100. nci.cbSize = sizeof(NONCLIENTMETRICS);
  101. SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
  102. sizeof(NONCLIENTMETRICS), &nci, 0);
  103. tip_font = CreateFontIndirect(&nci.lfStatusFont);
  104. }
  105. /* Generate the tip text */
  106. sprintf(str, "%dx%d", cx, cy);
  107. if (!tip_wnd) {
  108. HDC hdc;
  109. SIZE sz;
  110. RECT wr;
  111. int ix, iy;
  112. /* calculate the tip's size */
  113. hdc = CreateCompatibleDC(NULL);
  114. GetTextExtentPoint32(hdc, str, _tcslen(str), &sz);
  115. DeleteDC(hdc);
  116. GetWindowRect(src, &wr);
  117. ix = wr.left;
  118. if (ix < 16)
  119. ix = 16;
  120. iy = wr.top - sz.cy;
  121. if (iy < 16)
  122. iy = 16;
  123. /* Create the tip window */
  124. tip_wnd =
  125. CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
  126. MAKEINTRESOURCE(tip_class), str, WS_POPUP, ix,
  127. iy, sz.cx, sz.cy, NULL, NULL, hinst, NULL);
  128. ShowWindow(tip_wnd, SW_SHOWNOACTIVATE);
  129. } else {
  130. /* Tip already exists, just set the text */
  131. SetWindowText(tip_wnd, str);
  132. }
  133. }
  134. void EnableSizeTip(bool bEnable)
  135. {
  136. if (tip_wnd && !bEnable) {
  137. DestroyWindow(tip_wnd);
  138. tip_wnd = NULL;
  139. }
  140. tip_enabled = bEnable;
  141. }