home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / WRITEPAD.PAK / RULER.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  22.7 KB  |  843 lines

  1. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright (C) 1993-1995  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  MODULE:   ruler.c
  9. //
  10. //  PURPOSE:   
  11. //
  12. //  FUNCTIONS:
  13. //    Ruler           - Processes messages for ruler box
  14. //
  15. //  COMMENTS:
  16. //
  17. //
  18.  
  19. #include <windows.h>            // required for all Windows applications
  20. #include <windowsx.h>
  21. #include <malloc.h>
  22. #include <commctrl.h>
  23. #include "globals.h"            // prototypes specific to this application
  24. #include "ruler.h"            // prototypes specific to this application
  25.  
  26. // Ruler dialog message table definition.
  27. MSD rgmsdRuler[] =
  28. {
  29.     {WM_CREATE,             MsgRulerCreate},
  30.     {WM_DESTROY,            MsgRulerDestroy},
  31.     {WM_PAINT,              MsgRulerPaint},
  32.     {WM_LBUTTONDOWN,        MsgRulerLButtonDown},
  33.     {WM_LBUTTONUP,          MsgRulerLButtonUp},
  34.     {WM_MOUSEMOVE,          MsgRulerMouseMove},
  35.     {WM_ERASEBKGND,         MsgRulerEraseBkgnd},
  36.     {RM_GETMARGINS,         MsgRulerGetMargins},
  37.     {RM_SETMARGINS,         MsgRulerSetMargins},
  38.     {RM_GETTABCOUNT,        MsgRulerGetTabCount},
  39.     {RM_GETTABS,            MsgRulerGetTabs},
  40.     {RM_SETTABS,            MsgRulerSetTabs}
  41. };
  42.  
  43. MSDI msdiRuler =
  44. {
  45.     sizeof(rgmsdRuler) / sizeof(MSD),
  46.     rgmsdRuler,
  47.     edwpWindow
  48. };
  49.  
  50.  
  51. // Module specific "globals"  Used when a variable needs to be
  52. // accessed in more than on handler function.
  53.  
  54. char szRulerName[] = SZRULERNAME;
  55.  
  56. typedef struct tagRULER
  57.     {
  58.     UINT    RULER_iLeftMargin ;   // All measurements in Twips
  59.     UINT    RULER_iRightMargin;
  60.     UINT    RULER_iIndent     ;
  61.     UINT    RULER_iLeftPage   ;
  62.     UINT    RULER_iRightPage  ;
  63.     LONG    RULER_lTabs[RULER_MAXTABS];
  64.     }
  65. RULER, FAR * LPRULER;
  66.  
  67. LPRULER    lpRuler;
  68. HIMAGELIST hRulerImageList;
  69. UINT       iRulerCount;
  70. BOOL       bDragging;
  71. int        iWhoToDrag;
  72. int        dyHotSpot;
  73.  
  74. // Image list constants
  75.  
  76. #define RULER_LEFTMARGIN  0
  77. #define RULER_RIGHTMARGIN 1
  78. #define RULER_INDENT      2
  79. #define RULER_LEFTTAB     3
  80.  
  81. // These macros are used to get at the ruler instance specific data
  82.  
  83. #define GETRULERPOINTER lpRuler = (LPRULER)GetWindowLong(hwnd,0)
  84. #define SETRULERPOINTER(lpRuler)  SetWindowLong(hwnd, 0, (LONG)lpRuler)
  85.  
  86. #define iLeftMargin  (lpRuler->RULER_iLeftMargin )
  87. #define iRightMargin (lpRuler->RULER_iRightMargin)
  88. #define iIndent      (lpRuler->RULER_iIndent     )
  89. #define iLeftPage    (lpRuler->RULER_iLeftPage   )
  90. #define iRightPage   (lpRuler->RULER_iRightPage  )
  91. #define lTabs        (lpRuler->RULER_lTabs       )
  92.  
  93. //
  94. //  FUNCTION: Ruler(HWND, UINT, WPARAM, LPARAM)
  95. //
  96. //  PURPOSE:  Processes messages for "Ruler" dialog box.
  97. //
  98. //  PARAMETERS:
  99. //    hdlg - window handle of the dialog box
  100. //    wMessage - type of message
  101. //    wparam - message-specific information
  102. //    lparam - message-specific information
  103. //
  104. //  RETURN VALUE:
  105. //    TRUE - message handled
  106. //    FALSE - message not handled
  107. //
  108. //  COMMENTS:
  109. //
  110. //     Display version information from the version section of the
  111. //     application resource.
  112. //
  113. //     Wait for user to click on "Ok" button, then close the dialog box.
  114. //
  115.  
  116. LRESULT CALLBACK Ruler(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  117. {
  118.     return DispMessage(&msdiRuler, hwnd, uMessage, wparam, lparam);
  119. }
  120.  
  121. HWND CreateRuler(HWND hwndParent, UINT uID, int dx, int dy)
  122. {
  123.     HINSTANCE hInst = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE);
  124.  
  125.     return CreateWindow(szRulerName,
  126.                         NULL,
  127.                         WS_CHILD | WS_VISIBLE,
  128.                         0,
  129.                         0,
  130.                         dx,
  131.                         dy,
  132.                         hwndParent,
  133.                         (HMENU)uID,
  134.                         hInst,
  135.                         NULL);
  136. }
  137.  
  138. //
  139. //  FUNCTION: MsgRulerCreate(HWND, UINT, WPARAM, LPARAM)
  140. //
  141. //  PURPOSE: To initialize the Ruler box 
  142. //
  143. //  PARAMETERS:
  144. //    hwnd - The window handing the message.
  145. //    uMessage - The message number. (unused).
  146. //    wparam - Message specific data (unused).
  147. //    lparam - Message specific data (unused).
  148. //
  149. //  RETURN VALUE:
  150. //    Always returns 0 - message handled.
  151. //
  152. //  COMMENTS:
  153. //    Uses the version apis to retrieve version information for
  154. //    each of the static text boxes in the Ruler box.
  155. //
  156.  
  157. #pragma argsused
  158. LRESULT MsgRulerCreate(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  159. {
  160.     int i;
  161.  
  162.     lpRuler = malloc(sizeof(RULER));
  163.     if (lpRuler)
  164.     {
  165.         SETRULERPOINTER(lpRuler);
  166.  
  167.         iLeftMargin  = 1440;
  168.         iRightMargin = 6*1440;
  169.         iIndent      = 1440+720;
  170.         iLeftPage    = 0;
  171.         iRightPage   = 7*1440;
  172.  
  173.         for (i = 0; i < RULER_MAXTABS; i++) lTabs[i] = 0;
  174.  
  175.         if (!hRulerImageList)
  176.         {
  177.             hRulerImageList = ImageList_LoadBitmap(hInst,
  178.                                                    MAKEINTRESOURCE(IDB_RULER),
  179.                                                    8,
  180.                                                    1,
  181.                                                    RGB(255,0,0)
  182.                                                   );
  183.         }
  184.         iRulerCount++;
  185.     }
  186.     return TRUE;
  187. }
  188.  
  189. //
  190. //  FUNCTION: MsgRulerCreate(HWND, UINT, WPARAM, LPARAM)
  191. //
  192. //  PURPOSE: To initialize the Ruler box 
  193. //
  194. //  PARAMETERS:
  195. //    hwnd - The window handing the message.
  196. //    uMessage - The message number. (unused).
  197. //    wparam - Message specific data (unused).
  198. //    lparam - Message specific data (unused).
  199. //
  200. //  RETURN VALUE:
  201. //    Always returns 0 - message handled.
  202. //
  203. //  COMMENTS:
  204. //    Uses the version apis to retrieve version information for
  205. //    each of the static text boxes in the Ruler box.
  206. //
  207.  
  208. #pragma argsused
  209. LRESULT MsgRulerDestroy(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  210. {
  211.     GETRULERPOINTER;
  212.     if (lpRuler) free(lpRuler);
  213.  
  214.     iRulerCount--;
  215.     if (!iRulerCount)
  216.     {
  217.         ImageList_Destroy(hRulerImageList);
  218.         hRulerImageList = NULL;
  219.     }
  220.  
  221.      return 0;
  222. }
  223.  
  224.  
  225. //
  226. //  FUNCTION: InitMDIChild(HINSTANCE)
  227. //
  228. //  PURPOSE: To register the MDI child window class.
  229. //
  230. //  PARAMETERS:
  231. //    hinst - The instance of the application used to register the class.
  232. //
  233. //  RETURN VALUE:
  234. //    TRUE - Succeeded in registering the class.
  235. //    FALSE - Failed to register the class.
  236. //
  237. //  COMMENTS:
  238. //
  239. //
  240.  
  241. BOOL InitRuler(HINSTANCE hinst)
  242. {
  243.     WNDCLASS  wc = {0};
  244.  
  245.     wc.lpfnWndProc   = (WNDPROC)Ruler;
  246.     wc.hIcon         = NULL;
  247.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  248.     wc.lpszMenuName  = NULL;
  249.     wc.hInstance     = hinst;                      // Owner of this class
  250.     wc.cbClsExtra    = 0;
  251.     wc.cbWndExtra    = sizeof(LPRULER);
  252.     wc.hbrBackground = GetStockObject(LTGRAY_BRUSH);
  253.     wc.lpszClassName = szRulerName;
  254.  
  255.     return (BOOL)RegisterClass(&wc);
  256. }
  257.  
  258. int TwipsToPixels (HDC hDC, int iTwips)
  259. {
  260.     POINT pt;
  261.     int   iOldMode;
  262.  
  263.     iOldMode = SetMapMode(hDC, MM_TWIPS);
  264.  
  265.     pt.x = iTwips;
  266.     pt.y = 0;
  267.  
  268.     LPtoDP(hDC, &pt, 1);
  269.  
  270.     SetMapMode(hDC, iOldMode);
  271.  
  272.     return pt.x;
  273. }
  274.  
  275. int PixelsToTwips (HDC hDC, int iPixels)
  276. {
  277.     POINT pt;
  278.     int   iOldMode;
  279.  
  280.     iOldMode = SetMapMode(hDC, MM_TWIPS);
  281.  
  282.     pt.x = iPixels;
  283.     pt.y = 0;
  284.  
  285.     DPtoLP(hDC, &pt, 1);
  286.  
  287.     SetMapMode(hDC, iOldMode);
  288.  
  289.     return pt.x;
  290. }
  291.  
  292. int InsertTab (HWND hwnd, int uPixelLocation)
  293. {
  294.     int     i;
  295.     int     iTwipValue;
  296.     HDC     hDC;
  297.  
  298.     GETRULERPOINTER;
  299.  
  300.     hDC = GetDC(hwnd);
  301.     iTwipValue = PixelsToTwips(hDC, uPixelLocation);
  302.     ReleaseDC(hwnd, hDC);
  303.  
  304.     for (i = 0; (lTabs[i]) && (i < RULER_MAXTABS); i++);
  305.     if (RULER_MAXTABS-1 == i) 
  306.         return -1; // no room!
  307.  
  308.     lTabs[i] = iTwipValue;
  309.  
  310.     return i;
  311. }
  312.  
  313. BOOL DeleteTab (HWND hwnd, int iWhoToRemove)
  314. {
  315.     int i;
  316.  
  317.     GETRULERPOINTER;
  318.  
  319.     for (i = iWhoToRemove; i < RULER_MAXTABS-1; i++)
  320.         lTabs[i] = lTabs[i+1];
  321.     lTabs[RULER_MAXTABS-1] = 0;
  322.     return TRUE;        
  323. }
  324.  
  325. void SortTabs (HWND hwnd)
  326. {
  327.     int  i, j;
  328.     LONG temp;
  329.  
  330.     GETRULERPOINTER;
  331.  
  332.     for (i = 0; i < RULER_MAXTABS-1; i++)
  333.         for (j = 0; j < RULER_MAXTABS-1; j++)
  334.             if ((!lTabs[j]) || ((lTabs[j] > lTabs[j+1])&&(lTabs[j+1])))
  335.             {
  336.                 temp        = lTabs[j];
  337.                 lTabs[j]    = lTabs[j+1];
  338.                 lTabs[j+1]  = temp;
  339.             }
  340. }
  341.  
  342. #pragma argsused
  343. LRESULT MsgRulerEraseBkgnd(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  344. {
  345.     return 0L;    
  346. }
  347.  
  348.  
  349. //
  350. //  FUNCTION: MsgRulerCreate(HWND, UINT, WPARAM, LPARAM)
  351. //
  352. //  PURPOSE: To initialize the Ruler box 
  353. //
  354. //  PARAMETERS:
  355. //    hwnd - The window handing the message.
  356. //    uMessage - The message number. (unused).
  357. //    wparam - Message specific data (unused).
  358. //    lparam - Message specific data (unused).
  359. //
  360. //  RETURN VALUE:
  361. //    Always returns 0 - message handled.
  362. //
  363. //  COMMENTS:
  364. //    Uses the version apis to retrieve version information for
  365. //    each of the static text boxes in the Ruler box.
  366. //
  367.  
  368. #pragma argsused
  369. LRESULT MsgRulerPaint(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  370. {
  371.      HDC           hDC, hMemDC;
  372.     HBITMAP       hBitmap;
  373.     PAINTSTRUCT   ps;
  374.     int           iTickLeft;
  375.     int           iTickRight;
  376.     int           iTickIndent;
  377.     int           iPixelsPerEigth;
  378.     RECT          rc, rcWindow;
  379.     int           i, iCount;
  380.     char          sz[16];
  381.     HPEN          hOldPen, hHighlight, hShadow;
  382.     HBRUSH        hOldBrush;
  383.  
  384.     GETRULERPOINTER;
  385.  
  386.      hDC = BeginPaint(hwnd, &ps);
  387.  
  388.     if ((lpRuler) && (hRulerImageList))
  389.     {
  390.         GetClientRect(hwnd, &rcWindow);
  391.  
  392.         hMemDC  = CreateCompatibleDC(hDC);
  393.         hBitmap = CreateCompatibleBitmap(hDC, rcWindow.right, rcWindow.bottom);
  394.         hBitmap = SelectObject(hMemDC,hBitmap);
  395.         FillRect(hMemDC, 
  396.                  &rcWindow, 
  397.                  (HBRUSH)GetClassLong(hwnd, GCL_HBRBACKGROUND));
  398.  
  399.         // Step 1: Lay Down the gray and white sections
  400.  
  401.           GetClientRect(hwnd, &rc);
  402.         rc.left  = TwipsToPixels (hMemDC, iLeftPage);
  403.         rc.right = TwipsToPixels (hMemDC, iRightPage);
  404.         rc.top   = 4;
  405.         rc.bottom= 27;
  406.         SetBkColor (hMemDC, RGB(255,255,255));
  407.         ExtTextOut (hMemDC, rc.left, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
  408.  
  409.         // Step 2: Draw the highlights/shadows
  410.  
  411.         hHighlight = CreatePen(PS_SOLID, 1, RGB(255,255,255));
  412.         hShadow    = CreatePen(PS_SOLID, 1, RGB(128,128,128));
  413.  
  414.         hOldPen   = SelectObject(hMemDC, hHighlight);
  415.         hOldBrush = SelectObject(hMemDC, GetStockObject(NULL_BRUSH));
  416.  
  417.         SelectObject(hMemDC, hShadow);
  418.  
  419.         Rectangle(hMemDC, min(iLeftPage,4), 4, rc.right+1, 28);
  420.  
  421.         SelectObject(hMemDC, hHighlight);
  422.         Rectangle(hMemDC, min (iLeftPage,4)+1, 5, rcWindow.right+1, 29);
  423.         MoveToEx(hMemDC, min (iLeftPage,4), 28, NULL);
  424.         LineTo(hMemDC, min (iLeftPage,4), 29);
  425.  
  426.         Rectangle (hMemDC, rc.right+1, 5, rcWindow.right+1, 29);
  427.  
  428.         SelectObject (hMemDC, hShadow);
  429.         Rectangle (hMemDC, min (iLeftPage,4), 4, rc.left+1, 28);
  430.         Rectangle (hMemDC, rc.right, 4, rcWindow.right+1, 28);
  431.  
  432.         SelectObject (hMemDC, GetStockObject (BLACK_PEN));
  433.         MoveToEx(hMemDC, rc.left+1, 27, NULL);
  434.         LineTo(hMemDC, rc.left+1, 5);
  435.         LineTo(hMemDC, rc.right, 5);
  436.  
  437.         SelectObject(hMemDC, hOldPen);
  438.         SelectObject(hMemDC, hOldBrush);
  439.  
  440.         // Step 3: Draw the line with the margins
  441.  
  442.         SetBkMode(hMemDC, TRANSPARENT);
  443.         iPixelsPerEigth = TwipsToPixels(hMemDC, 1440/8);
  444.         GetClientRect(hwnd, &rc);
  445.         for (iCount = 0, i = 0; i <= rc.right; i+= iPixelsPerEigth, iCount++)
  446.           {
  447.             switch (iCount % 8)
  448.             {
  449.                 case 0: // On the inch
  450.  
  451.                     if (i)
  452.                     {
  453.                         RECT rcNum;
  454.                         rcNum.left = i-32;
  455.                         rcNum.right = i+32;
  456.                         rcNum.top = 0;
  457.                         rcNum.bottom = 32;
  458.                         wsprintf(sz, "%d", iCount/8);
  459.                         DrawText(hMemDC, sz, lstrlen(sz), &rcNum, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  460.                     }
  461.                           break;
  462.  
  463.                 case 4: // On the half inch
  464.  
  465.                     MoveToEx(hMemDC, i, 12, NULL);
  466.                     LineTo(hMemDC, i, 20);
  467.                     break;
  468.  
  469.                 default: // On the 8th inch
  470.  
  471.                     MoveToEx (hMemDC, i, 15, NULL);
  472.                     LineTo(hMemDC, i, 17);
  473.                     break;
  474.             }
  475.         }
  476.  
  477.         iTickLeft   = TwipsToPixels(hMemDC, iLeftMargin);
  478.         iTickRight  = TwipsToPixels(hMemDC, iRightMargin);
  479.         iTickIndent = TwipsToPixels(hMemDC, iIndent);
  480.  
  481.         ImageList_Draw(hRulerImageList,
  482.                        RULER_LEFTMARGIN,
  483.                        hMemDC,
  484.                        iTickLeft-4,
  485.                        16,
  486.                        ILD_TRANSPARENT);
  487.         ImageList_Draw(hRulerImageList,
  488.                        RULER_RIGHTMARGIN,
  489.                        hMemDC,
  490.                        iTickRight-4,
  491.                               16,
  492.                        ILD_TRANSPARENT);
  493.         ImageList_Draw(hRulerImageList,
  494.                        RULER_INDENT,
  495.                        hMemDC,
  496.                        iTickIndent-4,
  497.                        0,
  498.                        ILD_TRANSPARENT);
  499.  
  500.         for (i = 0; i < RULER_MAXTABS; i++)
  501.         {
  502.             if (lTabs[i]) 
  503.                 ImageList_Draw(hRulerImageList,
  504.                                RULER_LEFTTAB,
  505.                                hMemDC,
  506.                                          TwipsToPixels (hMemDC, lTabs[i]),
  507.                                11,
  508.                                ILD_TRANSPARENT);
  509.         }
  510.  
  511.         BitBlt(hDC, 0, 0, rcWindow.right, rcWindow.bottom, 
  512.                hMemDC, 0, 0, 
  513.                SRCCOPY);
  514.         hBitmap = SelectObject(hMemDC,hBitmap);
  515.         DeleteObject(hBitmap);
  516.         DeleteObject(hHighlight);
  517.         DeleteObject(hShadow);
  518.         DeleteDC(hMemDC);
  519.     }
  520.  
  521.      EndPaint(hwnd, &ps);
  522.  
  523.      return 0;
  524. }
  525.  
  526. #pragma argsused
  527. LRESULT MsgRulerLButtonDown(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  528. {
  529.     RECT          rc;
  530.     int           i;
  531.     int           iTickLeft;
  532.     int           iTickRight;
  533.     int           iTickIndent;
  534.      POINT         pt;
  535.      HDC           hDC;
  536.      int           iXPos = 0;
  537.      int           dxHotSpot;
  538.  
  539.      GETRULERPOINTER;
  540.  
  541.      pt.x = LOWORD(lparam);
  542.      pt.y = HIWORD(lparam);
  543.  
  544.      if (lpRuler)
  545.      {
  546.           iWhoToDrag = -1;
  547.  
  548.         hDC = GetDC(hwnd);
  549.  
  550.         iTickLeft   = TwipsToPixels(hDC, iLeftMargin);
  551.         iTickRight  = TwipsToPixels(hDC, iRightMargin);
  552.         iTickIndent = TwipsToPixels(hDC, iIndent);
  553.  
  554.         SetRect(&rc, iTickLeft-4, 16, iTickLeft+4, 32);
  555.         if (PtInRect(&rc, pt)) 
  556.         {
  557.             iWhoToDrag = RULER_LEFTMARGIN;
  558.             dxHotSpot  = pt.x - rc.left;
  559.             dyHotSpot  = 16;
  560.                 iXPos = rc.left;
  561.           }
  562.         SetRect(&rc, iTickRight-4, 16, iTickRight+4, 32);
  563.           if (PtInRect(&rc, pt))
  564.         {
  565.             iWhoToDrag = RULER_RIGHTMARGIN;
  566.             dxHotSpot  = pt.x - rc.left;
  567.                 dyHotSpot  = 16;
  568.             iXPos = rc.left;
  569.           }
  570.         SetRect(&rc, iTickIndent-4, 0, iTickIndent+4, 15);
  571.         if (PtInRect(&rc, pt)) 
  572.         {
  573.             iWhoToDrag = RULER_INDENT;
  574.             dxHotSpot  = pt.x - rc.left;
  575.             dyHotSpot  = 0;
  576.             iXPos = rc.left;
  577.         }
  578.         for (i = 0; i < RULER_MAXTABS && -1 == iWhoToDrag; i++)
  579.         {
  580.                 SetRect(&rc,
  581.                     TwipsToPixels(hDC,lTabs[i]), 10, 
  582.                     TwipsToPixels(hDC,lTabs[i])+6, 28);
  583.             if (PtInRect (&rc, pt)) 
  584.             {
  585.                 iWhoToDrag = RULER_LEFTTAB + i;
  586.                 dxHotSpot  = pt.x - rc.left;
  587.                 dyHotSpot  = 11;
  588.                      iXPos = rc.left;
  589.                 }
  590.           }
  591.  
  592.         ReleaseDC(hwnd, hDC);
  593.  
  594.           if (-1 == iWhoToDrag)
  595.         {
  596.             iWhoToDrag = InsertTab(hwnd, pt.x);
  597.             if (-1 != iWhoToDrag) 
  598.             {
  599.                 iWhoToDrag += RULER_LEFTTAB;
  600.                 dxHotSpot  = 0;
  601.                 dyHotSpot  = 11;
  602.                 iXPos = pt.x;
  603.                 }
  604.           }
  605.  
  606.         if (-1 != iWhoToDrag)
  607.         {
  608.                 bDragging = TRUE;
  609.             SetCapture (hwnd);
  610.  
  611.             ShowCursor ( FALSE );
  612.  
  613.             hDC = GetDC(hwnd);
  614.  
  615.             ImageList_Draw (hRulerImageList,
  616.                             min (RULER_LEFTTAB, iWhoToDrag) + 4,
  617.                             hDC,
  618.                             iXPos,
  619.                                      dyHotSpot,
  620.                             ILD_TRANSPARENT);
  621.  
  622.             ReleaseDC(hwnd, hDC);
  623.  
  624.             // Start the drag and drop procedure.
  625.             ImageList_BeginDrag(hRulerImageList,
  626.                                 min (RULER_LEFTTAB, iWhoToDrag),
  627.                                 dxHotSpot,
  628.                                 0);
  629.  
  630.             // Lock the window for painting the drag and drop
  631.             // image; this will cause the drag/drop image to
  632.             // appear.
  633.             ImageList_DragEnter(hwnd, iXPos+dxHotSpot, dyHotSpot);
  634.  
  635.         }
  636.     }
  637.     return 0;
  638. }
  639.  
  640. #pragma argsused
  641. LRESULT MsgRulerLButtonUp(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  642. {
  643.     int         iTabPos;
  644.     HDC       hDC;
  645.     NMRULER   nmruler;
  646.     RECT      rc;
  647.  
  648.     GETRULERPOINTER;
  649.     if (bDragging)
  650.     {
  651.         // Tell the Common Controls DD to stop the drag image
  652.         ImageList_EndDrag();
  653.         // Unlock any painting associated with the Image List's drag/drop
  654.         ImageList_DragLeave(hwnd);
  655.  
  656.         ReleaseCapture ();
  657.           ShowCursor(TRUE);
  658.         bDragging = FALSE;
  659.  
  660.         hDC = GetDC(hwnd);
  661.  
  662.         iTabPos = PixelsToTwips (hDC, LOWORD(lparam));
  663.  
  664.         if (-1 != iWhoToDrag)
  665.             switch (iWhoToDrag)
  666.             {
  667.                 case RULER_LEFTMARGIN:  iLeftMargin  = iTabPos;                    break;
  668.                 case RULER_INDENT:      iIndent      = iTabPos;                    break;
  669.                 case RULER_RIGHTMARGIN: iRightMargin = iTabPos;                    break;
  670.                      default:
  671.                             if ((HIWORD(lparam)>32)) // Out of bounds!
  672.                             {
  673.                          DeleteTab(hwnd, iWhoToDrag-RULER_LEFTTAB);
  674.                      }
  675.                      else
  676.                      {
  677.                          lTabs[iWhoToDrag-RULER_LEFTTAB] = iTabPos; 
  678.                          SortTabs(hwnd);
  679.                      }
  680.                      break;
  681.  
  682.                 }
  683.         InvalidateRect (hwnd, NULL, FALSE);
  684.  
  685.         GetClientRect(GetParent(hwnd), &rc);
  686.  
  687.           nmruler.nmhdr.hwndFrom   = hwnd;
  688.         nmruler.nmhdr.idFrom     = GetWindowLong(hwnd, GWL_ID);
  689.         nmruler.nmhdr.code       = RN_CHANGEDSETTINGS;
  690.         nmruler.iLeft            = iLeftMargin;
  691.         nmruler.iRight           = iRightPage - iRightMargin;
  692.         nmruler.iFirstLineIndent = iIndent;
  693.  
  694.         ReleaseDC(hwnd, hDC);
  695.  
  696.         // Notify the parent app the ruler's settings have changed
  697.         SendMessage (GetParent(hwnd), 
  698.                      WM_NOTIFY, 
  699.                      nmruler.nmhdr.idFrom, 
  700.                      (LPARAM)&nmruler);
  701.     }
  702.      return 0;
  703. }
  704.  
  705. #pragma argsused
  706. LRESULT MsgRulerMouseMove(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  707. {
  708.     if (bDragging) 
  709.     {
  710.         if (iWhoToDrag < RULER_LEFTTAB)
  711.         {
  712.             ImageList_DragMove(LOWORD(lparam), dyHotSpot);
  713.         }
  714.         else
  715.         {
  716.             if ((HIWORD(lparam)>32))
  717.                 ImageList_DragMove(LOWORD(lparam), 
  718.                                    dyHotSpot+GetSystemMetrics(SM_CYSCREEN));
  719.             else
  720.                 ImageList_DragMove(LOWORD(lparam), dyHotSpot);
  721.         }
  722.      }
  723.     return 0;
  724. }
  725.  
  726. #pragma argsused
  727. LRESULT MsgRulerGetMargins(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  728. {
  729.      HDC     hDC;
  730.      RECT    rc;
  731.     LPINT   iMargins = (LPINT)lparam;
  732.  
  733.     GETRULERPOINTER;
  734.  
  735.     GetClientRect(GetParent(hwnd), &rc);
  736.  
  737.     hDC = GetDC(hwnd); 
  738.     
  739.     iMargins[0] = iLeftMargin;
  740.     iMargins[1] = iRightPage - iRightMargin;
  741.     iMargins[2] = iIndent;
  742.     iMargins[3] = iLeftPage;
  743.     iMargins[4] = iRightPage;
  744.         
  745.      ReleaseDC(hwnd, hDC);
  746.     
  747.     return 0;
  748. }
  749.  
  750. #pragma argsused
  751. LRESULT MsgRulerSetMargins (HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  752. {
  753.     HDC     hDC;
  754.     RECT    rc;
  755.     LPINT   iMargins = (LPINT)lparam;
  756.     UINT    iTempLeft;
  757.     UINT    iTempRight;
  758.     UINT    iTempIndent;
  759.     UINT    iTempLeftPage;
  760.     UINT    iTempRightPage;
  761.  
  762.     GETRULERPOINTER;
  763.  
  764.     GetClientRect(GetParent(hwnd), &rc);
  765.  
  766.     hDC = GetDC(hwnd); 
  767.     
  768.     iTempLeft      = iMargins[0];
  769.     iTempRight     = iMargins[4] - iMargins[1];
  770.     iTempIndent    = iMargins[2];
  771.     iTempLeftPage  = iMargins[3];
  772.     iTempRightPage = iMargins[4];
  773.         
  774.     ReleaseDC(hwnd, hDC);
  775.  
  776.     if (
  777.          (iTempLeft      != iLeftMargin)  ||
  778.          (iTempRight     != iRightMargin) ||
  779.          (iTempIndent    != iIndent)      ||
  780.          (iTempLeftPage  != iLeftPage)    ||
  781.          (iTempRightPage != iRightPage)
  782.        )
  783.        {
  784.        iLeftMargin  = iTempLeft  ;
  785.        iRightMargin = iTempRight ;
  786.        iIndent      = iTempIndent; 
  787.        iLeftPage    = iTempLeftPage;
  788.        iRightPage   = iTempRightPage;
  789.        InvalidateRect (hwnd,NULL,FALSE);
  790.        }
  791.     
  792.     return 0;
  793. }
  794.  
  795. #pragma argsused
  796. LRESULT MsgRulerGetTabCount(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  797. {
  798.      int i, iCount;
  799.  
  800.      GETRULERPOINTER;
  801.  
  802.     iCount = 0;
  803.     for (i = 0; i < RULER_MAXTABS; i++) if (lTabs[i]) iCount++;
  804.     return (LPARAM)iCount;
  805. }
  806.  
  807. #pragma argsused
  808. LRESULT MsgRulerGetTabs(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  809. {
  810.      int i, iCount;
  811.      GETRULERPOINTER;
  812.  
  813.     iCount = 0;
  814.     for (i = 0; i < RULER_MAXTABS; i++) if (lTabs[i]) iCount++;
  815.     for (i = 0; i < min(iCount, (int)wparam); i++) ((LPLONG)lparam)[i] = lTabs[i];
  816.     return (LPARAM)iCount;
  817. }
  818.  
  819. #pragma argsused
  820. LRESULT MsgRulerSetTabs    (HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  821. {
  822.     int     i;
  823.     BOOL    bDiff;
  824.  
  825.     GETRULERPOINTER;
  826.  
  827.     bDiff = FALSE;
  828.     for (i = 0; i < min(RULER_MAXTABS, (int)wparam); i++)
  829.         if (lTabs[i] != ((LPLONG)lparam)[i]) bDiff = TRUE;
  830.     if (wparam+1 < (RULER_MAXTABS-1))
  831.         if (lTabs[wparam+1]) bDiff = TRUE;
  832.  
  833.     if (bDiff)
  834.     {
  835.         for (i = 0; i < RULER_MAXTABS; i++) lTabs[i] = 0;
  836.           for (i = 0; i < min(RULER_MAXTABS, (int)wparam); i++)
  837.             lTabs[i] = ((LPLONG)lparam)[i];
  838.         InvalidateRect(hwnd, NULL, FALSE);
  839.     }
  840.  
  841.     return 0L;
  842. }
  843.