Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1493 lines
47 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. // Copyright 1990-1993 Microsoft corporation
  3. // all rights reservered
  4. //////////////////////////////////////////////////////////////////////////////
  5. //
  6. // Program: (nominally)Bloodhound
  7. // Module: tab.c
  8. // Purpose: creates and operates a book tab (big file folder) custom control
  9. //
  10. // Note: the current implementation is limited to 4 booktabs, sorry.
  11. //
  12. //
  13. // ---------------------------- TABSTOP = 4 -------------------
  14. //
  15. // Entry Points:
  16. //
  17. // History
  18. // Arthur Brooking 8/06/93 created
  19. //////////////////////////////////////////////////////////////////////////////
  20. //////////////////////////////////////////////////////////////////////////////
  21. // BookTab
  22. //
  23. //
  24. //
  25. // Input:
  26. // hwnd - our window handle
  27. //
  28. // Returns:
  29. //
  30. //
  31. // History
  32. // Arthur Brooking 8/06/93 created
  33. //////////////////////////////////////////////////////////////////////////////
  34. #define STRICT
  35. #include "switches.h"
  36. #include <windows.h>
  37. #include <windowsx.h>
  38. #include "tab.h"
  39. // #include "..\bhmem.h"
  40. //////////////////////////////////////////////////////////////////////////////
  41. // Constants
  42. //////////////////////////////////////////////////////////////////////////////
  43. #define MAX_TABS 4
  44. #define MAX_TAB_LABEL_LEN 128
  45. #define ANGLE_X 5
  46. #define ANGLE_Y 5
  47. #define CARAT_X 2
  48. #define CARAT_Y 2
  49. #define FLUFF_X 0
  50. #define FLUFF_Y 0
  51. #define FOOTROOM_Y 3
  52. // We use the selected tab for these calculations:
  53. //
  54. // tab_rect:
  55. //
  56. // ANGLE_X|--|
  57. //
  58. // - BBBBBBBBBBBBBBB
  59. // ANGLE_Y | BWWWWWWWWWWWWWWW
  60. // | BWWWWWWWWWWWWWWWW
  61. // - BWWW
  62. // BWW * <-- this is where the text_rect starts
  63. // BWW
  64. // BWW
  65. //
  66. //
  67. // text_rect: (defined by the *'s)
  68. //
  69. // FLUFF_X|----|
  70. //
  71. // - * *
  72. // |
  73. // FLUFF_Y |
  74. // | CARAT_X
  75. // | |---|
  76. // - ............................. -
  77. // . . |
  78. // . . | CARAT_Y
  79. // . . |
  80. // - . XXXXX XXXXX X X XXXXX . -
  81. // text hght| . X X X X X .
  82. // is from | . X XXX X X .
  83. // font | . X X X X X .
  84. // _ . X XXXXX X X X .
  85. // . .
  86. // . .
  87. // . .
  88. // .............................
  89. //
  90. // |---------------------|
  91. // text width is directly
  92. // from the font itself
  93. // * *
  94. //
  95. //
  96. //////////////////////////////////////////////////////////////////////////////
  97. // Data Structures for this file
  98. //////////////////////////////////////////////////////////////////////////////
  99. typedef struct _ONETAB
  100. {
  101. TCHAR label[ MAX_TAB_LABEL_LEN + 1 ];
  102. DWORD data;
  103. RECT tab_rect;
  104. RECT text_rect;
  105. } ONETAB;
  106. typedef struct _TABDATA
  107. {
  108. // do the tabs need updating ?
  109. BOOL fUpdate;
  110. RECT tabs_rect;
  111. // font data
  112. HFONT hfSelected;
  113. HFONT hfUnselected;
  114. // windows data
  115. HWND hwndParent;
  116. // tab data
  117. UINT total_tabs;
  118. UINT selected_tab;
  119. ONETAB tab[ MAX_TABS ];
  120. } TABDATA;
  121. typedef TABDATA *LPTABDATA;
  122. //////////////////////////////////////////////////////////////////////////////
  123. // Variables Global to this file
  124. //////////////////////////////////////////////////////////////////////////////
  125. TCHAR szBookTabName[]=BOOK_TAB_CONTROL;
  126. //////////////////////////////////////////////////////////////////////////////
  127. // Macros Global to this file
  128. //////////////////////////////////////////////////////////////////////////////
  129. #define GetInstanceDataPtr(hwnd) ((LPTABDATA)GetWindowLongPtr(hwnd, 0))
  130. #define SetInstanceDataPtr(hwnd,x) (SetWindowLongPtr(hwnd, 0, (DWORD_PTR)x))
  131. //////////////////////////////////////////////////////////////////////////////
  132. // Functional Prototypes for Functions Local to this File
  133. //////////////////////////////////////////////////////////////////////////////
  134. LRESULT CALLBACK BookTab_WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  135. BOOL BookTab_OnCreate(HWND hwnd, CREATESTRUCT FAR* lpCreateStruct);
  136. void BookTab_OnDestroy(HWND hwnd);
  137. void BookTab_OnLButtonDown(HWND hwnd, BOOL fDblClk, int x, int y, UINT keyFlags);
  138. void BookTab_OnPaint(HWND hwnd);
  139. UINT BookTab_OnGetDlgCode(HWND hwnd, MSG FAR* lpmsg);
  140. void BookTab_OnSize(HWND hwnd, UINT state, int cx, int cy);
  141. void BookTab_OnSetFocus(HWND hwnd, HWND hwndOldFocus);
  142. void BookTab_OnKillFocus(HWND hwnd, HWND hwndNewFocus);
  143. void BookTab_OnKey(HWND hwnd, UINT vk, BOOL fDown, int cRepeat, UINT flags);
  144. void BookTab_OnEnable(HWND hwnd, BOOL fEnable);
  145. UINT BookTab_OnAddItem( HWND hwnd, LPTSTR text );
  146. UINT BookTab_OnInsertItem( HWND hwnd, UINT index, LPTSTR text);
  147. BOOL BookTab_OnDeleteItem( HWND hwnd, UINT index );
  148. BOOL BookTab_OnDeleteAllItems( HWND hwnd);
  149. BOOL BookTab_OnSetItem( HWND hwnd, UINT index, LPTSTR text );
  150. BOOL BookTab_OnGetItem( HWND hwnd, UINT index, LPTSTR text );
  151. UINT BookTab_OnSetCurSel( HWND hand, UINT newsel );
  152. UINT BookTab_OnGetCurSel( HWND hand );
  153. UINT BookTab_OnGetItemCount( HWND hwnd );
  154. BOOL BookTab_OnSetItemData( HWND hwnd, UINT index, DWORD data );
  155. DWORD BookTab_OnGetItemData( HWND hwnd, UINT index);
  156. void BookTab_OnPutInBack( HWND hwnd );
  157. BOOL IsPointInRect( int given_x, int given_y, LPRECT pRect );
  158. void BookTab_UpdateButtons( HWND hwnd );
  159. //////////////////////////////////////////////////////////////////////////////
  160. // BookTab_Initialize()
  161. //
  162. // Initializes and registers the BookTab custom class
  163. //
  164. // Input:
  165. // hInstance - the handle to our parent's instance
  166. //
  167. // Returns:
  168. // True if successful, else False
  169. //
  170. // History
  171. // Arthur Brooking 8/06/93 created
  172. //////////////////////////////////////////////////////////////////////////////
  173. void BookTab_Initialize(HINSTANCE hInstance)
  174. {
  175. WNDCLASS wndclass;
  176. wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS | CS_PARENTDC;
  177. wndclass.lpfnWndProc = BookTab_WndProc;
  178. wndclass.cbClsExtra = 0;
  179. wndclass.cbWndExtra = sizeof( LPTABDATA );
  180. wndclass.hInstance = hInstance;
  181. wndclass.hIcon = NULL;
  182. wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
  183. wndclass.hbrBackground = NULL;
  184. wndclass.lpszMenuName = NULL;
  185. wndclass.lpszClassName = szBookTabName;
  186. RegisterClass ( &wndclass );
  187. }
  188. //////////////////////////////////////////////////////////////////////////////
  189. // BookTab_WndProc()
  190. //
  191. // Distributes messages coming in to the BookTab control
  192. //
  193. // Input:
  194. // hwnd - Our handle
  195. // message - the ordinal of the incoming message
  196. // wParam - half of the incoming data
  197. // lParam - the other half of the incoming data
  198. //
  199. // Returns:
  200. // True if we handled the message, else False
  201. //
  202. // History
  203. // Arthur Brooking 8/06/93 created
  204. //////////////////////////////////////////////////////////////////////////////
  205. LRESULT CALLBACK BookTab_WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  206. {
  207. switch (message)
  208. {
  209. // standard windows messages
  210. HANDLE_MSG( hwnd, WM_CREATE, BookTab_OnCreate);
  211. HANDLE_MSG( hwnd, WM_DESTROY, BookTab_OnDestroy);
  212. HANDLE_MSG( hwnd, WM_LBUTTONDOWN, BookTab_OnLButtonDown);
  213. HANDLE_MSG( hwnd, WM_PAINT, BookTab_OnPaint);
  214. HANDLE_MSG( hwnd, WM_SIZE, BookTab_OnSize);
  215. HANDLE_MSG( hwnd, WM_SETFOCUS, BookTab_OnSetFocus);
  216. HANDLE_MSG( hwnd, WM_KILLFOCUS, BookTab_OnKillFocus);
  217. HANDLE_MSG( hwnd, WM_KEYDOWN, BookTab_OnKey);
  218. HANDLE_MSG( hwnd, WM_KEYUP, BookTab_OnKey);
  219. // messages specific to all custom controls
  220. HANDLE_MSG( hwnd, WM_GETDLGCODE, BookTab_OnGetDlgCode);
  221. HANDLE_MSG( hwnd, WM_ENABLE, BookTab_OnEnable);
  222. // messages specific to THIS custom control
  223. case BT_ADDITEM:
  224. return( BookTab_OnAddItem( hwnd, (LPTSTR)lParam ));
  225. case BT_INSERTITEM:
  226. return( BookTab_OnInsertItem( hwnd, (UINT)wParam, (LPTSTR)lParam ));
  227. case BT_DELETEITEM:
  228. return( BookTab_OnDeleteItem( hwnd, (UINT)wParam ));
  229. case BT_DELETEALLITEMS:
  230. return( BookTab_OnDeleteAllItems( hwnd ));
  231. case BT_SETITEM:
  232. return( BookTab_OnSetItem( hwnd, (UINT)wParam, (LPTSTR)lParam ));
  233. case BT_GETITEM:
  234. return( BookTab_OnGetItem( hwnd, (UINT)wParam, (LPTSTR)lParam ));
  235. case BT_SETCURSEL:
  236. return( BookTab_OnSetCurSel( hwnd, (UINT)wParam ));
  237. case BT_GETCURSEL:
  238. return( BookTab_OnGetCurSel( hwnd ));
  239. case BT_GETITEMCOUNT:
  240. return( BookTab_OnGetItemCount( hwnd ));
  241. case BT_SETITEMDATA:
  242. return( BookTab_OnSetItemData( hwnd, (UINT)wParam, (DWORD)lParam ));
  243. case BT_GETITEMDATA:
  244. return( BookTab_OnGetItemData( hwnd, (UINT)wParam ));
  245. case BT_PUTINBACK:
  246. BookTab_OnPutInBack( hwnd );
  247. return (TRUE);
  248. }
  249. // pass unprocessed messages to DefWndProc...
  250. return DefWindowProc(hwnd, message, wParam, lParam);
  251. }
  252. //////////////////////////////////////////////////////////////////////////////
  253. // BookTab_OnCreate()
  254. //
  255. // Initializes a new instance of our lovely custom control
  256. //
  257. // Input:
  258. // hwnd - our window handle
  259. // lpcreatestruct - pointer to the data with which to do our thing
  260. //
  261. // Returns:
  262. // True if the instance is created, else false
  263. //
  264. // History
  265. // Arthur Brooking 8/06/93 created
  266. //////////////////////////////////////////////////////////////////////////////
  267. BOOL BookTab_OnCreate(HWND hwnd, CREATESTRUCT FAR* lpCreateStruct)
  268. {
  269. LPTABDATA pData;
  270. UINT i;
  271. // allocate the instance data for this control
  272. pData = LocalAlloc( LPTR, sizeof( TABDATA ));
  273. if( pData == NULL )
  274. return FALSE;
  275. SetInstanceDataPtr( hwnd, pData );
  276. // initialize values in the control
  277. pData->total_tabs = 0;
  278. pData->selected_tab = 0;
  279. pData->hwndParent = lpCreateStruct->hwndParent;
  280. // fill the prospective tab slots with data
  281. for( i = 0; i < MAX_TABS; i++ )
  282. {
  283. pData->tab[i].label[0] = TEXT('\0');
  284. pData->tab[i].data = (DWORD)0;
  285. }
  286. // create the proper fonts:
  287. // 8 pt sans serif bold for selected and
  288. // 8 pt sans serif regular for not selected
  289. pData->hfSelected = CreateFont( -MulDiv(9, GetDeviceCaps(GetDC(hwnd),
  290. LOGPIXELSY), 72), 0, 0, 0,
  291. FW_BOLD, FALSE, FALSE, FALSE,
  292. DEFAULT_CHARSET, OUT_TT_PRECIS,
  293. CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
  294. 0x4, TEXT("MS Shell Dlg") );
  295. pData->hfUnselected = CreateFont( -MulDiv(9, GetDeviceCaps(GetDC(hwnd),
  296. LOGPIXELSY), 72), 0, 0, 0,
  297. FW_NORMAL, FALSE, FALSE, FALSE,
  298. DEFAULT_CHARSET, OUT_TT_PRECIS,
  299. CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
  300. 0x4, TEXT("MS Shell Dlg") );
  301. // fill the rest of the sizing info
  302. BookTab_OnSize( hwnd, 0, lpCreateStruct->cx, lpCreateStruct->cy );
  303. // make sure that we are on the bottom
  304. SetWindowPos( hwnd, HWND_BOTTOM, 0, 0, 0, 0,
  305. SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW );
  306. // make sure we update
  307. pData->fUpdate = TRUE;
  308. // put us last
  309. BookTab_PutInBack( hwnd );
  310. return TRUE;
  311. }
  312. //////////////////////////////////////////////////////////////////////////////
  313. // BookTab_OnDestroy()
  314. //
  315. // Cleans up as our control goes away
  316. //
  317. // Input:
  318. // hwnd - our window handle
  319. //
  320. // Returns:
  321. // nothing
  322. //
  323. // History
  324. // Arthur Brooking 8/06/93 created
  325. //////////////////////////////////////////////////////////////////////////////
  326. void BookTab_OnDestroy(HWND hwnd)
  327. {
  328. LPTABDATA pData;
  329. // get the instance data
  330. pData = GetInstanceDataPtr( hwnd );
  331. // delete our fonts
  332. DeleteObject( pData->hfSelected );
  333. DeleteObject( pData->hfUnselected );
  334. // free up our instance data
  335. LocalFree( pData );
  336. }
  337. //////////////////////////////////////////////////////////////////////////////
  338. // BookTab_OnLButtonDown()
  339. //
  340. // Handles the event where a user has the left mouse button down
  341. //
  342. // Input:
  343. // hwnd - our window handle
  344. // fDblClk - an indication on the second message of a double click
  345. // x - the mouses x coordinate at the time of the message
  346. // y - the mouses y coordinate at the time of the message
  347. // keyFlags - an indication of which keys were pressed at the time
  348. //
  349. // Returns:
  350. // nuthin'
  351. //
  352. // History
  353. // Arthur Brooking 8/06/93 created
  354. //////////////////////////////////////////////////////////////////////////////
  355. void BookTab_OnLButtonDown(HWND hwnd, BOOL fDblClk, int x, int y, UINT keyFlags)
  356. {
  357. LPTABDATA pData;
  358. UINT i;
  359. // get the instance data
  360. pData = GetInstanceDataPtr( hwnd );
  361. // where did they click the mouse...
  362. // loop thru the tabs to find the one struck
  363. for( i = 0; i < pData->total_tabs; i++ )
  364. {
  365. if( IsPointInRect( x, y, &(pData->tab[i].tab_rect) ) )
  366. {
  367. // this is the correct spot
  368. BookTab_OnSetCurSel( hwnd, i );
  369. // notify our parent that the selection has changed
  370. SendMessage( pData->hwndParent, BTN_SELCHANGE,
  371. pData->selected_tab, (DWORD_PTR)hwnd);
  372. SetFocus( hwnd );
  373. return;
  374. }
  375. }
  376. // the mouse was clicked outside any of the button areas
  377. }
  378. //////////////////////////////////////////////////////////////////////////////
  379. // BookTab_OnPaint()
  380. //
  381. // Handles requests from windows that the control repaint itself
  382. //
  383. // Input:
  384. // hwnd - our window handle
  385. //
  386. // Returns:
  387. // hopefully :)
  388. //
  389. // History
  390. // Arthur Brooking 8/06/93 created
  391. //////////////////////////////////////////////////////////////////////////////
  392. void BookTab_OnPaint(HWND hwnd)
  393. {
  394. LPTABDATA pData;
  395. PAINTSTRUCT ps;
  396. HDC hdc;
  397. TEXTMETRIC tm;
  398. UINT i;
  399. HWND hwndFocus;
  400. HPEN hOldPen;
  401. HPEN hShadowPen;
  402. HPEN hHighlightPen;
  403. HPEN hFramePen;
  404. HPEN hBackPen;
  405. HBRUSH hBackBrush;
  406. HFONT hfOldFont;
  407. WORD cyChar;
  408. WORD yWidth;
  409. WORD xWidth;
  410. RECT total;
  411. RECT temp;
  412. LPRECT pTab;
  413. LPRECT pText;
  414. // get the instance data
  415. pData = GetInstanceDataPtr( hwnd );
  416. // right before drawing, make sure that the button sizes are accurate
  417. BookTab_UpdateButtons( hwnd );
  418. // get the instance data
  419. pData = GetInstanceDataPtr( hwnd );
  420. // get the handle to the window with the current focus
  421. hwndFocus = GetFocus();
  422. // prepare for painting...
  423. BeginPaint( hwnd, &ps );
  424. hdc = GetDC( hwnd );
  425. // set text stuff
  426. SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
  427. SetTextColor(hdc, GetSysColor(COLOR_BTNTEXT));
  428. SetTextAlign( hdc, TA_TOP | TA_LEFT );
  429. // determine proper sizes
  430. GetTextMetrics(hdc, &tm);
  431. cyChar = (WORD)tm.tmHeight;
  432. xWidth = (WORD) GetSystemMetrics(SM_CXBORDER);
  433. yWidth = (WORD) GetSystemMetrics(SM_CYBORDER);
  434. GetClientRect( hwnd, &total );
  435. //BUGBUG fudge the rectangle so that the bottom and left do not get cut off
  436. total.bottom -= yWidth;
  437. total.right -= xWidth;
  438. // set up the pens that we will need
  439. hHighlightPen = CreatePen(PS_SOLID, yWidth, GetSysColor(COLOR_BTNHIGHLIGHT));
  440. hShadowPen = CreatePen(PS_SOLID, yWidth, GetSysColor(COLOR_BTNSHADOW));
  441. hFramePen = CreatePen(PS_SOLID, yWidth, GetSysColor(COLOR_WINDOWFRAME));
  442. hBackPen = CreatePen(PS_SOLID, yWidth, GetSysColor(COLOR_BTNFACE));
  443. hBackBrush = CreateSolidBrush( GetSysColor(COLOR_BTNFACE));
  444. // get the old pen by setting a new one
  445. hOldPen = SelectPen( hdc, hHighlightPen );
  446. // clear out behind the tabs if we need to
  447. if( pData->fUpdate == TRUE )
  448. {
  449. FillRect( hdc, &(pData->tabs_rect), hBackBrush );
  450. pData->fUpdate = FALSE;
  451. }
  452. // draw the box...
  453. // left side dark border
  454. SelectPen( hdc, hFramePen );
  455. MoveToEx( hdc, total.left, pData->tab[0].tab_rect.bottom+yWidth, NULL );
  456. LineTo ( hdc, total.left, total.bottom );
  457. // bottom dark border
  458. LineTo ( hdc, total.right, total.bottom );
  459. // right side dark border
  460. LineTo ( hdc, total.right, pData->tab[0].tab_rect.bottom+yWidth);
  461. // top dark border, right half (over to selection)
  462. LineTo ( hdc, pData->tab[pData->selected_tab].tab_rect.right-yWidth,
  463. pData->tab[0].tab_rect.bottom+yWidth);
  464. // skip area under the selected tab
  465. MoveToEx( hdc, pData->tab[pData->selected_tab].tab_rect.left,
  466. pData->tab[0].tab_rect.bottom+yWidth, NULL);
  467. // top dark border, left half (from selection to left border)
  468. LineTo ( hdc, total.left, pData->tab[0].tab_rect.bottom+yWidth);
  469. // left side highlight #1
  470. SelectPen( hdc, hHighlightPen );
  471. MoveToEx( hdc, total.left+xWidth, pData->tab[0].tab_rect.bottom+2*yWidth, NULL );
  472. LineTo( hdc, total.left+xWidth, total.bottom-yWidth );
  473. // bottom shadow #1
  474. SelectPen( hdc, hShadowPen );
  475. LineTo( hdc, total.right-xWidth, total.bottom-yWidth );
  476. // right side shadow #1
  477. LineTo( hdc, total.right-xWidth, pData->tab[0].tab_rect.bottom+2*yWidth );
  478. // top hilite #1
  479. SelectPen( hdc, hHighlightPen );
  480. // top hilite, right half (over to selection)
  481. LineTo ( hdc, pData->tab[pData->selected_tab].tab_rect.right-yWidth,
  482. pData->tab[0].tab_rect.bottom+2*yWidth);
  483. // skip area under the selected tab
  484. MoveToEx( hdc, pData->tab[pData->selected_tab].tab_rect.left,
  485. pData->tab[0].tab_rect.bottom+2*yWidth, NULL);
  486. // top hilite, left half (from selection to left border)
  487. if( pData->selected_tab != 0 )
  488. LineTo ( hdc, total.left+2*xWidth,
  489. pData->tab[0].tab_rect.bottom+2*yWidth);
  490. // left side highlight #2
  491. SelectPen( hdc, hHighlightPen );
  492. MoveToEx( hdc, total.left+2*xWidth, pData->tab[0].tab_rect.bottom+3*yWidth, NULL );
  493. LineTo( hdc, total.left+2*xWidth, total.bottom-2*yWidth );
  494. // bottom shadow #2
  495. SelectPen( hdc, hShadowPen );
  496. LineTo( hdc, total.right-2*xWidth, total.bottom-2*yWidth );
  497. // right side shadow #2
  498. LineTo( hdc, total.right-2*xWidth, pData->tab[0].tab_rect.bottom+3*yWidth );
  499. // top hilite #2
  500. SelectPen( hdc, hHighlightPen );
  501. // top hilite, right half (over to selection)
  502. LineTo ( hdc, pData->tab[pData->selected_tab].tab_rect.right-2*yWidth,
  503. pData->tab[0].tab_rect.bottom+3*yWidth);
  504. // skip area under the selected tab
  505. MoveToEx( hdc, pData->tab[pData->selected_tab].tab_rect.left,
  506. pData->tab[0].tab_rect.bottom+3*yWidth, NULL);
  507. // top hilite, left half (from selection to left border)
  508. if( pData->selected_tab != 0 )
  509. LineTo ( hdc, total.left+2*xWidth,
  510. pData->tab[0].tab_rect.bottom+3*yWidth);
  511. // Draw the tabs...
  512. // loop thru the tabs
  513. for( i = 0; i < pData->total_tabs; i++ )
  514. {
  515. // point our local variables at the current rects
  516. pTab = &(pData->tab[i].tab_rect);
  517. pText = &(pData->tab[i].text_rect);
  518. if( i == pData->selected_tab )
  519. {
  520. // this is the selection, it should not be pushed down...
  521. // left side dark border
  522. SelectPen( hdc, hFramePen );
  523. MoveToEx(hdc, pTab->left, pTab->bottom, NULL);
  524. LineTo(hdc, pTab->left, pTab->top + ANGLE_Y*yWidth);
  525. // left side angle dark border
  526. LineTo(hdc, pTab->left + ANGLE_X*xWidth, pTab->top);
  527. // top dark border
  528. LineTo(hdc, pTab->right - ANGLE_X*xWidth, pTab->top);
  529. // right side angle dark border
  530. LineTo(hdc, pTab->right, pTab->top + ANGLE_Y*yWidth);
  531. // right side dark border (overshoot by one)
  532. LineTo(hdc, pTab->right, pTab->bottom+yWidth);
  533. // left side hilite #1 (extends down 3 below the box to handle
  534. // melding the hilites with the box below)
  535. SelectPen( hdc, hHighlightPen);
  536. MoveToEx(hdc, pTab->left+xWidth, pTab->bottom+3*yWidth, NULL);
  537. LineTo(hdc, pTab->left+xWidth, pTab->top+ANGLE_Y*yWidth );
  538. // left side angle hilight #1
  539. LineTo(hdc, pTab->left+ANGLE_X*xWidth, pTab->top+yWidth );
  540. // top hilite #1
  541. LineTo(hdc, pTab->right-ANGLE_X*xWidth, pTab->top+yWidth );
  542. // right side angle shadow #1
  543. SelectPen( hdc, hShadowPen);
  544. LineTo(hdc, pTab->right-xWidth, pTab->top+ANGLE_Y*yWidth );
  545. // right side shadow #1 (overshoot by one) (see above)
  546. LineTo(hdc, pTab->right-xWidth, pTab->bottom+3*yWidth);
  547. // left side hilite #2 (the 2* are becaus we are the 2nd hilite)
  548. SelectPen( hdc, hHighlightPen);
  549. MoveToEx(hdc, pTab->left+2*xWidth, pTab->bottom+3*yWidth, NULL);
  550. LineTo(hdc, pTab->left+2*xWidth, pTab->top+ANGLE_Y*yWidth );
  551. // left side angle hilight #2
  552. LineTo(hdc, pTab->left+ANGLE_X*xWidth, pTab->top+2*yWidth );
  553. // top hilite #2
  554. LineTo(hdc, pTab->right-ANGLE_X*xWidth, pTab->top+2*yWidth );
  555. // right side angle shadow #2
  556. SelectPen( hdc, hShadowPen);
  557. LineTo(hdc, pTab->right-2*xWidth, pTab->top+ANGLE_Y*yWidth );
  558. // right side shadow #2 (overshoot by one)
  559. LineTo(hdc, pTab->right-2*xWidth, pTab->bottom+4*yWidth );
  560. // clear out the chunk below the active tab
  561. SelectPen(hdc, hBackPen );
  562. MoveToEx(hdc, pTab->left+3*xWidth, pTab->bottom+yWidth, NULL);
  563. LineTo(hdc, pTab->right-2*xWidth, pTab->bottom+yWidth);
  564. MoveToEx(hdc, pTab->left+3*xWidth, pTab->bottom+2*yWidth, NULL);
  565. LineTo(hdc, pTab->right-2*xWidth, pTab->bottom+2*yWidth);
  566. MoveToEx(hdc, pTab->left+3*xWidth, pTab->bottom+3*yWidth, NULL);
  567. LineTo(hdc, pTab->right-2*xWidth, pTab->bottom+3*yWidth);
  568. // clear out the old label...
  569. FillRect( hdc, pText, hBackBrush );
  570. // now print in the label ...
  571. hfOldFont = SelectObject( hdc, pData->hfSelected );
  572. ExtTextOut( hdc,
  573. pText->left+ CARAT_X*xWidth + FLUFF_X*xWidth,
  574. pText->top + CARAT_Y*yWidth + FLUFF_Y*yWidth,
  575. 0, NULL, pData->tab[i].label,
  576. lstrlen(pData->tab[i].label), NULL );
  577. SelectFont( hdc, hfOldFont );
  578. // if we have the focus, print the caret
  579. if( hwnd == hwndFocus )
  580. {
  581. // we have the focus
  582. temp.top = pText->top + FLUFF_X*xWidth;
  583. temp.left = pText->left + FLUFF_Y*yWidth;
  584. temp.bottom = pText->bottom - FLUFF_X*xWidth;
  585. temp.right = pText->right - FLUFF_Y*yWidth;
  586. DrawFocusRect( hdc, &temp );
  587. }
  588. }
  589. else
  590. {
  591. // push this tab down one border width...
  592. // this will mean an extra +1 on all ANGLE_Ys...
  593. // left side dark border
  594. SelectPen( hdc, hFramePen );
  595. MoveToEx(hdc, pTab->left, pTab->bottom, NULL);
  596. LineTo(hdc, pTab->left, pTab->top + (ANGLE_Y+1)*yWidth);
  597. // left side angle dark border
  598. LineTo(hdc, pTab->left + ANGLE_X*xWidth, pTab->top+yWidth);
  599. // top dark border
  600. LineTo(hdc, pTab->right - ANGLE_X*yWidth, pTab->top+yWidth);
  601. // right side angle dark border
  602. LineTo(hdc, pTab->right, pTab->top + (ANGLE_Y+1)*yWidth);
  603. // right side dark border (overshoot by one)
  604. LineTo(hdc, pTab->right, pTab->bottom+yWidth);
  605. // left side hilite
  606. SelectPen( hdc, hHighlightPen);
  607. MoveToEx(hdc, pTab->left+xWidth, pTab->bottom, NULL);
  608. LineTo(hdc, pTab->left+xWidth, pTab->top+(ANGLE_Y+1)*yWidth);
  609. // left side angle hilight
  610. LineTo(hdc, pTab->left+ANGLE_X*xWidth, pTab->top+2*yWidth);
  611. // top hilite
  612. LineTo(hdc, pTab->right-ANGLE_X*xWidth, pTab->top+2*yWidth);
  613. // right side angle shadow
  614. SelectPen( hdc, hShadowPen);
  615. LineTo(hdc, pTab->right-xWidth, pTab->top+(ANGLE_Y+1)*yWidth);
  616. // right side shadow (overshoot by one)
  617. LineTo(hdc, pTab->right-xWidth, pTab->bottom+yWidth);
  618. // clean above left angle
  619. SelectPen( hdc, hBackPen );
  620. MoveToEx(hdc, pTab->left, pTab->top+ANGLE_Y*yWidth, NULL );
  621. LineTo(hdc, pTab->left+ANGLE_X*xWidth, pTab->top );
  622. // clean above top
  623. LineTo(hdc, pTab->right-ANGLE_X*xWidth, pTab->top);
  624. // clean above right angle
  625. LineTo(hdc, pTab->right, pTab->top+ANGLE_Y*yWidth );
  626. // clean last corner
  627. LineTo(hdc, pTab->right, pTab->top+(ANGLE_Y+1)*yWidth );
  628. // clean up inside left hilite
  629. MoveToEx(hdc, pTab->left+2*xWidth, pTab->bottom, NULL );
  630. LineTo(hdc, pTab->left+2*xWidth, pTab->top+(ANGLE_Y+1)*yWidth);
  631. // clean up inside left angle hilite
  632. LineTo(hdc, pTab->left+ANGLE_X*xWidth, pTab->top+3*yWidth);
  633. // clean up inside top hilite (noop)
  634. LineTo(hdc, pTab->right-ANGLE_X*xWidth, pTab->top+3*yWidth);
  635. // clean up inside right angle shadow (noop)
  636. LineTo(hdc, pTab->right-2*xWidth, pTab->top+(ANGLE_Y+1)*yWidth);
  637. // clean up inside left hilite (overshoot by one)
  638. LineTo(hdc, pTab->right-2*xWidth, pTab->bottom+yWidth);
  639. // clear out the old label...
  640. FillRect( hdc, pText, hBackBrush );
  641. // now print in the label ...
  642. hfOldFont = SelectObject( hdc, pData->hfUnselected );
  643. ExtTextOut( hdc,
  644. pText->left+ CARAT_X*xWidth + FLUFF_X*xWidth,
  645. pText->top + CARAT_Y*yWidth + FLUFF_Y*yWidth + yWidth,
  646. 0, NULL, pData->tab[i].label,
  647. lstrlen(pData->tab[i].label), NULL );
  648. SelectFont( hdc, hfOldFont );
  649. }
  650. }
  651. SelectPen( hdc, hOldPen);
  652. // put the DC we used back into circulation
  653. ReleaseDC( hwnd, hdc );
  654. // tell windows that we're done
  655. EndPaint( hwnd, &ps );
  656. // clean up
  657. DeleteObject( hHighlightPen );
  658. DeleteObject( hShadowPen );
  659. DeleteObject( hFramePen );
  660. DeleteObject( hBackPen );
  661. DeleteObject( hBackBrush );
  662. }
  663. //////////////////////////////////////////////////////////////////////////////
  664. // BookTab_OnSize()
  665. //
  666. // Handles requests from windows that we should resize ourselves
  667. //
  668. // Input:
  669. // hwnd - our window handle
  670. // state - an indication of Minimized, maximized, iconic, blah blah blah
  671. // cx - our new width
  672. // cy - our new height
  673. //
  674. // Returns:
  675. // hopefully :)
  676. //
  677. // History
  678. // Arthur Brooking 8/06/93 created
  679. //////////////////////////////////////////////////////////////////////////////
  680. void BookTab_OnSize(HWND hwnd, UINT state, int cx, int cy)
  681. {
  682. // need to update the button size stuff, just for hit testing
  683. BookTab_UpdateButtons(hwnd);
  684. }
  685. //////////////////////////////////////////////////////////////////////////////
  686. // BookTab_OnSetFocus()
  687. //
  688. // Handles windows telling us that we just got the focus
  689. //
  690. // Input:
  691. // hwnd - our window handle
  692. // hwndOld - the guy who used to have the focus (i don't use)
  693. //
  694. // Returns:
  695. // nyaytay
  696. //
  697. // History
  698. // Arthur Brooking 8/06/93 created
  699. //////////////////////////////////////////////////////////////////////////////
  700. void BookTab_OnSetFocus(HWND hwnd, HWND hwndOldFocus)
  701. {
  702. LPTABDATA pData;
  703. // get the instance data
  704. pData = GetInstanceDataPtr( hwnd );
  705. // make sure that we are on the bottom
  706. SetWindowPos( hwnd, HWND_BOTTOM, 0, 0, 0, 0,
  707. SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW );
  708. // we gotta repaint just the rect for the active tab
  709. InvalidateRect( hwnd, &(pData->tab[pData->selected_tab].tab_rect), FALSE );
  710. UpdateWindow( hwnd );
  711. }
  712. //////////////////////////////////////////////////////////////////////////////
  713. // BookTab_OnKillFocus()
  714. //
  715. // Handles windows telling us that we are just about to lose the focus
  716. //
  717. // Input:
  718. // hwnd - our window handle
  719. // hwndNew - the lucky guy who is about to have the focus (i don't use)
  720. //
  721. // Returns:
  722. // nyaytay
  723. //
  724. // History
  725. // Arthur Brooking 8/06/93 created
  726. //////////////////////////////////////////////////////////////////////////////
  727. void BookTab_OnKillFocus(HWND hwnd, HWND hwndNewFocus)
  728. {
  729. LPTABDATA pData;
  730. // get the instance data
  731. pData = GetInstanceDataPtr( hwnd );
  732. // we gotta repaint just the rect for the active tab
  733. InvalidateRect( hwnd, &(pData->tab[pData->selected_tab].tab_rect), FALSE );
  734. UpdateWindow( hwnd );
  735. }
  736. //////////////////////////////////////////////////////////////////////////////
  737. // BookTab_OnKey()
  738. //
  739. // Handes key messages sent to the control
  740. //
  741. // Input:
  742. // hwnd - our window handle
  743. // vk - the virtual key code
  744. // fDown - is the key down?
  745. // cRepeat - how many times it was pressed
  746. // flags - i don't use
  747. //
  748. // Returns:
  749. // nada
  750. //
  751. // History
  752. // Arthur Brooking 8/06/93 created
  753. //////////////////////////////////////////////////////////////////////////////
  754. void BookTab_OnKey(HWND hwnd, UINT vk, BOOL fDown, int cRepeat, UINT flags)
  755. {
  756. LPTABDATA pData;
  757. // get the instance data
  758. pData = GetInstanceDataPtr( hwnd );
  759. // don't want key up messages
  760. if( fDown == FALSE )
  761. return;
  762. // we only handle left and right cursor
  763. switch( vk )
  764. {
  765. case VK_LEFT:
  766. // move to the tab to the left (wrap if needed)
  767. BookTab_OnSetCurSel( hwnd, (pData->selected_tab == 0)?
  768. (pData->total_tabs-1):(pData->selected_tab-1));
  769. // notify our parent that the selection has changed
  770. SendMessage( pData->hwndParent, BTN_SELCHANGE,
  771. pData->selected_tab, (DWORD_PTR)hwnd);
  772. break;
  773. case VK_RIGHT:
  774. BookTab_OnSetCurSel( hwnd,
  775. (pData->selected_tab+1) % (pData->total_tabs));
  776. // notify our parent that the selection has changed
  777. SendMessage( pData->hwndParent, BTN_SELCHANGE,
  778. pData->selected_tab, (DWORD_PTR)hwnd);
  779. break;
  780. }
  781. }
  782. //////////////////////////////////////////////////////////////////////////////
  783. // BookTab_OnGetDlgCode()
  784. //
  785. // The windows dialog manager is asking us what type of user inputs we want
  786. //
  787. // Input:
  788. // hwnd - our window handle
  789. // lpmsg - who knows, I don't use it, it's not in the paper docs...
  790. //
  791. // Returns:
  792. // a word which is a bitmap of input types
  793. //
  794. // History
  795. // Arthur Brooking 8/06/93 created
  796. //////////////////////////////////////////////////////////////////////////////
  797. UINT BookTab_OnGetDlgCode(HWND hwnd, MSG FAR* lpmsg)
  798. {
  799. // We just want cursor keys and character keys
  800. return( DLGC_WANTARROWS | DLGC_WANTCHARS );
  801. }
  802. //////////////////////////////////////////////////////////////////////////////
  803. // BookTab_OnEnable()
  804. //
  805. // Windows is telling us that we are being enabled/disabled
  806. //
  807. // Input:
  808. // hwnd - our window handle
  809. // fEnable - Are we being enabled?
  810. //
  811. // Returns:
  812. // nada
  813. //
  814. // History
  815. // Arthur Brooking 8/06/93 created
  816. //////////////////////////////////////////////////////////////////////////////
  817. void BookTab_OnEnable(HWND hwnd, BOOL fEnable)
  818. {
  819. // BUGBUG - we look no different in either state
  820. }
  821. //////////////////////////////////////////////////////////////////////////////
  822. // BookTab_OnAddItem()
  823. //
  824. // Adds an item to the end of the tab list
  825. //
  826. // Input:
  827. // hwnd - our window handle
  828. // text - the label of the tab to add
  829. //
  830. // Returns:
  831. // the index of the item as added
  832. //
  833. // History
  834. // Arthur Brooking 8/06/93 created
  835. //////////////////////////////////////////////////////////////////////////////
  836. UINT BookTab_OnAddItem( HWND hwnd, LPTSTR text )
  837. {
  838. LPTABDATA pData;
  839. // get the instance data
  840. pData = GetInstanceDataPtr( hwnd );
  841. // call the worker for insert with the current end of the tab lizst
  842. return( BookTab_OnInsertItem( hwnd, pData->total_tabs, text) );
  843. }
  844. //////////////////////////////////////////////////////////////////////////////
  845. // BookTab_OnInsertItem()
  846. //
  847. // Inserts the given item at the spot indicated and shoves the others down
  848. //
  849. // Input:
  850. // hwnd - our window handle
  851. // index - the proposed index of the new item
  852. // text - the label to add to the new tab
  853. //
  854. // Returns:
  855. // the ACTUAL new index of the item (we could sort or have to reduce
  856. // the initial request if it would leave a gap)
  857. //
  858. // History
  859. // Arthur Brooking 8/06/93 created
  860. //////////////////////////////////////////////////////////////////////////////
  861. UINT BookTab_OnInsertItem( HWND hwnd, UINT index, LPTSTR text)
  862. {
  863. LPTABDATA pData;
  864. int i;
  865. // get the instance data
  866. pData = GetInstanceDataPtr( hwnd );
  867. // make sure that the text will fit
  868. if( lstrlen( text ) > MAX_TAB_LABEL_LEN-1 )
  869. return (UINT)-1;
  870. // are we full
  871. // BUGBUG, limit in the future
  872. if( pData->total_tabs >= MAX_TABS )
  873. // we can not add at this time
  874. return (UINT)-1;
  875. // make sure that the requested index is within or adjacent to currently
  876. // used spots
  877. if( index > pData->total_tabs )
  878. // change it so that index now points at the next open slot
  879. index = pData->total_tabs;
  880. // slide over all tabs above
  881. for( i = (int)pData->total_tabs; i > (int)index; i-- )
  882. {
  883. memcpy( &(pData->tab[i]), &(pData->tab[i-1]), sizeof( ONETAB) );
  884. }
  885. // your room is ready sir
  886. lstrcpy( pData->tab[index].label, text );
  887. pData->total_tabs++;
  888. // should clear the background
  889. pData->fUpdate = TRUE;
  890. return index;
  891. }
  892. //////////////////////////////////////////////////////////////////////////////
  893. // BookTab_OnDeleteItem()
  894. //
  895. // Deletes the item at the index given and closes up the gaps
  896. //
  897. // Input:
  898. // hwnd - our window handle
  899. // index - item to be deleted
  900. //
  901. // Returns:
  902. // nuthin'
  903. //
  904. // History
  905. // Arthur Brooking 8/06/93 created
  906. //////////////////////////////////////////////////////////////////////////////
  907. BOOL BookTab_OnDeleteItem( HWND hwnd, UINT index )
  908. {
  909. LPTABDATA pData;
  910. UINT i;
  911. // get the instance data
  912. pData = GetInstanceDataPtr( hwnd );
  913. // make sure that we even have an element like this
  914. if( index >= pData->total_tabs )
  915. return FALSE;
  916. // slide all of the deceased successors over
  917. for( i = index+1; i < pData->total_tabs; i++ )
  918. {
  919. memcpy( &(pData->tab[i-1]), &(pData->tab[i]), sizeof( ONETAB) );
  920. }
  921. // reduce the count to account for the deletion
  922. pData->total_tabs--;
  923. // should clear the background
  924. pData->fUpdate = TRUE;
  925. return TRUE;
  926. }
  927. //////////////////////////////////////////////////////////////////////////////
  928. // BookTab_OnDeleteAllItems()
  929. //
  930. // Genocide on tabs
  931. //
  932. // Input:
  933. // hwnd - our window handle
  934. //
  935. // Returns:
  936. // nothing
  937. //
  938. // History
  939. // Arthur Brooking 8/06/93 created
  940. //////////////////////////////////////////////////////////////////////////////
  941. BOOL BookTab_OnDeleteAllItems( HWND hwnd)
  942. {
  943. LPTABDATA pData;
  944. // get the instance data
  945. pData = GetInstanceDataPtr( hwnd );
  946. // BUGBUG just set our count to zero
  947. pData->total_tabs = 0;
  948. return TRUE;
  949. }
  950. //////////////////////////////////////////////////////////////////////////////
  951. // BookTab_OnSetItem()
  952. //
  953. // Sets the title of the booktab given
  954. //
  955. // Input:
  956. // hwnd - our window handle
  957. // index - the tab to label
  958. // text - the words to put on the tab
  959. //
  960. // Returns:
  961. // TRUE if successful, else False
  962. //
  963. // History
  964. // Arthur Brooking 8/06/93 created
  965. //////////////////////////////////////////////////////////////////////////////
  966. BOOL BookTab_OnSetItem( HWND hwnd, UINT index, LPTSTR text )
  967. {
  968. LPTABDATA pData;
  969. // get the instance data
  970. pData = GetInstanceDataPtr( hwnd );
  971. // make sure that the text will fit
  972. if( lstrlen( text ) > MAX_TAB_LABEL_LEN-1 )
  973. return FALSE;
  974. // make sure that the index is legal
  975. if( index >= pData->total_tabs )
  976. return FALSE;
  977. // set the title
  978. lstrcpy( pData->tab[index].label, text );
  979. // we are changing the size of the tab, we will need to clean out behind
  980. pData->fUpdate = TRUE;
  981. return TRUE;
  982. }
  983. //////////////////////////////////////////////////////////////////////////////
  984. // BookTab_OnGetItem()
  985. //
  986. // Retrieves a booktab title
  987. //
  988. // Input:
  989. // hwnd - our window handle
  990. // index - the tab to label
  991. // text - the buffer to fill with the tab title
  992. //
  993. // Returns:
  994. // a pointer to the filled buffer if successful, else NULL
  995. //
  996. // History
  997. // Arthur Brooking 8/06/93 created
  998. //////////////////////////////////////////////////////////////////////////////
  999. BOOL BookTab_OnGetItem( HWND hwnd, UINT index, LPTSTR text )
  1000. {
  1001. LPTABDATA pData;
  1002. // get the instance data
  1003. pData = GetInstanceDataPtr( hwnd );
  1004. // make sure that the index is legal
  1005. if( index >= pData->total_tabs )
  1006. return FALSE;
  1007. // get the title
  1008. lstrcpy( text, pData->tab[index].label );
  1009. return( TRUE );
  1010. }
  1011. //////////////////////////////////////////////////////////////////////////////
  1012. // BookTab_OnSetCurSel()
  1013. //
  1014. // Sets the current selection
  1015. //
  1016. // Input:
  1017. // hwnd - our window handle
  1018. // newsel - the requested selection
  1019. //
  1020. // Returns:
  1021. // the new current selection
  1022. //
  1023. // History
  1024. // Arthur Brooking 8/06/93 created
  1025. //////////////////////////////////////////////////////////////////////////////
  1026. UINT BookTab_OnSetCurSel( HWND hwnd, UINT newsel )
  1027. {
  1028. LPTABDATA pData;
  1029. // get the instance data
  1030. pData = GetInstanceDataPtr( hwnd );
  1031. // make sure that the requested selection is within the proper bounds
  1032. if( newsel >= pData->total_tabs )
  1033. return( pData->selected_tab );
  1034. // make sure that the selection actually changed
  1035. if( newsel != pData->selected_tab )
  1036. {
  1037. // set selection
  1038. pData->selected_tab = newsel;
  1039. // make us redraw
  1040. InvalidateRect( hwnd, NULL, FALSE );
  1041. UpdateWindow( hwnd );
  1042. }
  1043. return( pData->selected_tab );
  1044. }
  1045. //////////////////////////////////////////////////////////////////////////////
  1046. // BookTab_GetCurSel()
  1047. //
  1048. // Retrieves the current selection
  1049. //
  1050. // Input:
  1051. // hwnd - our window handle
  1052. //
  1053. // Returns:
  1054. // the current selection
  1055. //
  1056. // History
  1057. // Arthur Brooking 8/06/93 created
  1058. //////////////////////////////////////////////////////////////////////////////
  1059. UINT BookTab_OnGetCurSel( HWND hwnd )
  1060. {
  1061. LPTABDATA pData;
  1062. // get the instance data
  1063. pData = GetInstanceDataPtr( hwnd );
  1064. // get selection
  1065. return( pData->selected_tab );
  1066. }
  1067. //////////////////////////////////////////////////////////////////////////////
  1068. // BookTab_OnGetItemCount()
  1069. //
  1070. // Retrieves the number of tabs currently in use
  1071. //
  1072. // Input:
  1073. // hwnd - our window handle
  1074. //
  1075. // Returns:
  1076. // the number of tabs in use
  1077. //
  1078. // History
  1079. // Arthur Brooking 8/06/93 created
  1080. //////////////////////////////////////////////////////////////////////////////
  1081. UINT BookTab_OnGetItemCount( HWND hwnd )
  1082. {
  1083. LPTABDATA pData;
  1084. // get the instance data
  1085. pData = GetInstanceDataPtr( hwnd );
  1086. // get the number of tabs
  1087. return( pData->total_tabs );
  1088. }
  1089. //////////////////////////////////////////////////////////////////////////////
  1090. // BookTab_OnSetItemData()
  1091. //
  1092. // Adds a DWORD of data to the data structure for the given tab
  1093. //
  1094. // Input:
  1095. // hwnd - our window handle
  1096. // index - which tab to add data to
  1097. // data - what to add
  1098. //
  1099. // Returns:
  1100. // TRUE if succcessful, else FALSE
  1101. //
  1102. // History
  1103. // Arthur Brooking 8/06/93 created
  1104. //////////////////////////////////////////////////////////////////////////////
  1105. BOOL BookTab_OnSetItemData( HWND hwnd, UINT index, DWORD data )
  1106. {
  1107. LPTABDATA pData;
  1108. // get the instance data
  1109. pData = GetInstanceDataPtr( hwnd );
  1110. // set the instance data
  1111. pData->tab[index].data = data;
  1112. return TRUE;
  1113. }
  1114. //////////////////////////////////////////////////////////////////////////////
  1115. // BookTab_OnPutInBack()
  1116. //
  1117. // Sets the focus to the booktab and then back to whoever had it first,
  1118. // this seemes to put this control in the very back.
  1119. //
  1120. // Input:
  1121. // hwnd - our window handle
  1122. //
  1123. // Returns:
  1124. // <nothing>
  1125. //
  1126. // History
  1127. // Arthur Brooking 1/21/93 created
  1128. //////////////////////////////////////////////////////////////////////////////
  1129. void BookTab_OnPutInBack( HWND hwnd )
  1130. {
  1131. HWND hwndOldFocus;
  1132. // set the focus to us
  1133. hwndOldFocus = SetFocus( hwnd );
  1134. // if there was an old focus, set it back to that.
  1135. if( hwndOldFocus )
  1136. SetFocus( hwndOldFocus );
  1137. }
  1138. //////////////////////////////////////////////////////////////////////////////
  1139. // BookTab_OnGetItemData()
  1140. //
  1141. // Gets the DWORD of data stored in the data structure for the given tab
  1142. //
  1143. // Input:
  1144. // hwnd - our window handle
  1145. // index - which tab to get data from
  1146. //
  1147. // Returns:
  1148. // the stored DWORD
  1149. //
  1150. // History
  1151. // Arthur Brooking 8/06/93 created
  1152. //////////////////////////////////////////////////////////////////////////////
  1153. DWORD BookTab_OnGetItemData( HWND hwnd, UINT index)
  1154. {
  1155. LPTABDATA pData;
  1156. // get the instance data
  1157. pData = GetInstanceDataPtr( hwnd );
  1158. // get the instance data
  1159. return( (DWORD)pData->tab[index].data );
  1160. }
  1161. //////////////////////////////////////////////////////////////////////////////
  1162. // IsPointInRect()
  1163. //
  1164. // determines if the point specifier is in the rectangle specified
  1165. //
  1166. // Input:
  1167. // given_x - x coordinate of the point to be tested
  1168. // given_y - y coordinate of the point to be tested
  1169. // pTab - a pointer to the rectangle to test against
  1170. //
  1171. // Returns:
  1172. // True if the point is within the rectangle, False if not
  1173. //
  1174. // History
  1175. // Arthur Brooking 8/06/93 created
  1176. //////////////////////////////////////////////////////////////////////////////
  1177. BOOL IsPointInRect( int given_x, int given_y, LPRECT pRect )
  1178. {
  1179. // is it above
  1180. if( given_y < pRect->top )
  1181. return FALSE;
  1182. // is it below
  1183. if( given_y > pRect->bottom )
  1184. return FALSE;
  1185. // is it to the left
  1186. if( given_x < pRect->left )
  1187. return FALSE;
  1188. // is it to the right
  1189. if( given_x > pRect->right )
  1190. return FALSE;
  1191. // well, it must be inside
  1192. return TRUE;
  1193. }
  1194. //////////////////////////////////////////////////////////////////////////////
  1195. // BookTab_UpdateButtons()
  1196. //
  1197. // Takes the current data and updates the sizes of the tabs
  1198. //
  1199. // Input:
  1200. // hwnd - our window handle
  1201. //
  1202. // Returns:
  1203. // nuthin
  1204. //
  1205. // History
  1206. // Arthur Brooking 8/06/93 created
  1207. //////////////////////////////////////////////////////////////////////////////
  1208. void BookTab_UpdateButtons( HWND hwnd )
  1209. {
  1210. LPTABDATA pData;
  1211. HDC hdc;
  1212. SIZE cur_size;
  1213. RECT total_rect;
  1214. WORD yWidth;
  1215. WORD xWidth;
  1216. UINT left;
  1217. UINT i;
  1218. HFONT hfOldFont;
  1219. // get the instance data
  1220. pData = GetInstanceDataPtr( hwnd );
  1221. // preset this so that the MAXes later will work
  1222. pData->tabs_rect.bottom = 0;
  1223. xWidth = (WORD) GetSystemMetrics(SM_CXBORDER);
  1224. yWidth = (WORD) GetSystemMetrics(SM_CYBORDER);
  1225. GetClientRect( hwnd, &total_rect);
  1226. // BUGBUG cheat to see the whole thing
  1227. total_rect.bottom -= yWidth;
  1228. total_rect.right -= xWidth;
  1229. hdc = GetDC( hwnd );
  1230. // use the selected font (BOLD) to size the tabs
  1231. hfOldFont = SelectObject( hdc, pData->hfSelected );
  1232. // loop thru the tabs
  1233. left = total_rect.left;
  1234. for( i = 0; i < pData->total_tabs; i++ )
  1235. {
  1236. // get the size of the data for this tab
  1237. GetTextExtentPoint( hdc, pData->tab[i].label,
  1238. lstrlen( pData->tab[i].label), &cur_size);
  1239. // calculate the text rectatangle first ...
  1240. // the text top is down the size of the angle
  1241. pData->tab[i].text_rect.top = total_rect.top + ANGLE_Y*yWidth;
  1242. // the text left is over the size of the angle
  1243. pData->tab[i].text_rect.left = left + ANGLE_X*xWidth;
  1244. // the text bottom is down from the top the size of the text +
  1245. // 2x the fluff(top and bottom) + 2x the carat space
  1246. pData->tab[i].text_rect.bottom = pData->tab[i].text_rect.top +
  1247. cur_size.cy + 2*FLUFF_Y*yWidth + 2*CARAT_Y*yWidth;
  1248. // the text right is over from the left the size of the text +
  1249. // 2x the fluff(left and right) + 2x the carat space
  1250. pData->tab[i].text_rect.right = pData->tab[i].text_rect.left +
  1251. cur_size.cx + 2*FLUFF_X*xWidth + 2*CARAT_X*xWidth;
  1252. // then calculate the full tab rectangle
  1253. // the tab top is the top of the control
  1254. pData->tab[i].tab_rect.top = total_rect.top;
  1255. // the left side of the tab is next to the previous right
  1256. pData->tab[i].tab_rect.left = left;
  1257. // the tab bottom is down the footroom from the text bottom
  1258. pData->tab[i].tab_rect.bottom = pData->tab[i].text_rect.bottom +
  1259. FOOTROOM_Y*yWidth;
  1260. // the tab right is over the size of the angle from the text right
  1261. pData->tab[i].tab_rect.right = pData->tab[i].text_rect.right +
  1262. ANGLE_Y*yWidth;
  1263. // set the left for the next guy to be our right
  1264. left = pData->tab[i].tab_rect.right;
  1265. // set the bottom of the all tabs rectangle
  1266. pData->tabs_rect.bottom = max( pData->tabs_rect.bottom,
  1267. pData->tab[i].tab_rect.bottom);
  1268. // BUGBUG check for run off the side
  1269. }
  1270. // set the rest of the cumulative tabs rect
  1271. pData->tabs_rect.top = total_rect.top;
  1272. pData->tabs_rect.right = total_rect.right;
  1273. pData->tabs_rect.left = total_rect.left;
  1274. // BUGBUG why
  1275. pData->tabs_rect.bottom++;
  1276. // reset the font
  1277. SelectObject( hdc, hfOldFont );
  1278. // free up the resources used
  1279. ReleaseDC( hwnd, hdc );
  1280. }
  1281. //////////////////////////////////////////////////////////////////////////////
  1282. // BookTab_()
  1283. //
  1284. //
  1285. //
  1286. // Input:
  1287. // hwnd - our window handle
  1288. //
  1289. // Returns:
  1290. //
  1291. //
  1292. // History
  1293. // Arthur Brooking 8/06/93 created
  1294. //////////////////////////////////////////////////////////////////////////////