home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / THREADS1.ZIP / THREADS1.C next >
C/C++ Source or Header  |  1990-01-09  |  12KB  |  370 lines

  1. /*----------------------------------------------------------------
  2.    THREADS1.C -- Demonstrates off-screen drawing in second thread
  3.                  (c) 1990, Ziff Communications Co.
  4.                  PC Magazine * Charles Petzold, 1/89
  5.   ----------------------------------------------------------------*/
  6.  
  7. #define INCL_GPI
  8. #define INCL_DOSPROCESS
  9. #include <os2.h>
  10. #include <mt\process.h>
  11. #include <mt\stdlib.h>
  12. #include <mt\string.h>
  13.  
  14. #define FONTNAME              "Tms Rmn Bold"
  15. #define XFONTSIZE             500            // in points
  16. #define YFONTSIZE             500
  17. #define TEXT                  "PC"
  18. #define TEXTLEN               (LONG) strlen (TEXT)
  19. #define BKGNDCOLOR            CLR_BLUE
  20. #define DIVISIONS             64             // number of spline areas
  21.  
  22. #define LCID_FONT             1L
  23. #define ID_PATH               1L
  24. #define STACKSIZE             (4096 * sizeof (int))
  25. #define RGB(r,g,b)            (((LONG) (r) << 16) | ((g) << 8) | (b))
  26. #define WM_BITMAP_CREATED     (WM_USER + 0)
  27.  
  28. typedef struct
  29.      {
  30.      int       aiThreadStack[STACKSIZE / sizeof (int)] ;
  31.      HBITMAP   hbm ;
  32.      HWND      hwndNotify ;
  33.      }
  34.      THREADPARAMS ;
  35.  
  36. MPARAM EXPENTRY ClientWndProc    (HWND, USHORT, MPARAM, MPARAM) ;
  37. VOID   FAR      SecondThread     (THREADPARAMS *) ;
  38. HBITMAP         CreateBitmap     (HAB) ;
  39. VOID            DrawImage        (HPS, SIZEL *) ;
  40. LONG            CreateVectorFont (HPS, LONG, CHAR *) ;
  41. VOID            Message          (HWND, SHORT, CHAR *) ;
  42.  
  43. int main (void)
  44.      {
  45.      static CHAR  szClientClass[] = "Threads1" ;
  46.      static ULONG flFrameFlags = FCF_TITLEBAR      | FCF_SYSMENU |
  47.                                  FCF_SIZEBORDER    | FCF_MINMAX  |
  48.                                  FCF_SHELLPOSITION | FCF_TASKLIST ;
  49.      HAB          hab ;
  50.      HMQ          hmq ;
  51.      HWND         hwndFrame, hwndClient ;
  52.      QMSG         qmsg ;
  53.  
  54.      hab = WinInitialize (0) ;
  55.      hmq = WinCreateMsgQueue (hab, 0) ;
  56.      WinRegisterClass (hab, szClientClass, ClientWndProc, CS_SIZEREDRAW, 0) ;
  57.  
  58.      hwndFrame = WinCreateStdWindow (HWND_DESKTOP, WS_VISIBLE,
  59.                                      &flFrameFlags, szClientClass, NULL,
  60.                                      0L, NULL, 0, &hwndClient) ;
  61.  
  62.      while (WinGetMsg (hab, &qmsg, NULL, 0, 0))
  63.           WinDispatchMsg (hab, &qmsg) ;
  64.  
  65.      WinDestroyWindow (hwndFrame) ;
  66.      WinDestroyMsgQueue (hmq) ;
  67.      WinTerminate (hab) ;
  68.      return 0 ;
  69.      }
  70.  
  71. MPARAM EXPENTRY ClientWndProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  72.      {
  73.      static BOOL      fError = FALSE ;
  74.      static HBITMAP   hbm ;
  75.      BITMAPINFOHEADER bmp ;
  76.      HPS              hps ;
  77.      POINTL           ptl ;
  78.      RECTL            rclClient ;
  79.      THREADPARAMS     *ptp ;
  80.  
  81.      switch (msg)
  82.           {
  83.           case WM_CREATE:
  84.                               // allocate memory for thread structure
  85.  
  86.                if ((ptp = malloc (sizeof (THREADPARAMS))) == NULL)
  87.                     {
  88.                     Message (hwnd, MB_ICONEXCLAMATION,
  89.                              "Cannot allocate memory for thread!") ;
  90.                     return 0 ;
  91.                     }
  92.  
  93.                ptp->hwndNotify = hwnd ;
  94.  
  95.                               // start the thread
  96.  
  97.                if (_beginthread (SecondThread, ptp->aiThreadStack,
  98.                                  STACKSIZE, ptp) == -1)
  99.                     {
  100.                     free (ptp) ;
  101.                     Message (hwnd, MB_ICONEXCLAMATION,
  102.                              "Cannot create print thread!") ;
  103.                     return 0 ;
  104.                     }
  105.                return 0 ;
  106.  
  107.           case WM_BITMAP_CREATED:
  108.                ptp = PVOIDFROMMP (mp1) ;
  109.                hbm = ptp->hbm ;
  110.                free (ptp) ;
  111.  
  112.                if (hbm == NULL)
  113.                     fError = TRUE ;
  114.  
  115.                WinInvalidateRect (hwnd, NULL, FALSE) ;
  116.                return 0 ;
  117.  
  118.           case WM_PAINT:
  119.                hps = WinBeginPaint (hwnd, NULL, NULL) ;
  120.                WinQueryWindowRect (hwnd, &rclClient) ;
  121.  
  122.                if (fError == TRUE)
  123.                     WinDrawText (hps, -1,
  124.                                  "Error occurred during bitmap creation.",
  125.                                  &rclClient, 0L, 0L, DT_CENTER | DT_VCENTER |
  126.                                  DT_TEXTATTRS | DT_ERASERECT) ;
  127.  
  128.                else if (hbm == NULL)
  129.                     WinDrawText (hps, -1,
  130.                                  "Bitmap being created....",
  131.                                  &rclClient, 0L, 0L, DT_CENTER | DT_VCENTER |
  132.                                  DT_TEXTATTRS | DT_ERASERECT) ;
  133.                else
  134.                     {
  135.                     WinFillRect (hps, &rclClient, BKGNDCOLOR) ;
  136.                     GpiQueryBitmapParameters (hbm, &bmp) ;
  137.                     ptl.x = (rclClient.xRight - bmp.cx) / 2 ;
  138.                     ptl.y = (rclClient.yTop   - bmp.cy) / 2 ;
  139.                     WinDrawBitmap (hps, hbm, NULL, &ptl, 0L, 0L, DBM_NORMAL) ;
  140.                     }
  141.  
  142.                WinEndPaint (hps) ;
  143.                return 0 ;
  144.  
  145.           case WM_DESTROY:
  146.                if (hbm != NULL)
  147.                     GpiDeleteBitmap (hbm) ;
  148.  
  149.                return 0 ;
  150.           }
  151.      return WinDefWindowProc (hwnd, msg, mp1, mp2) ;
  152.      }
  153.  
  154. VOID FAR SecondThread (THREADPARAMS *ptp)
  155.      {
  156.      HAB   hab ;
  157.  
  158.      hab = WinInitialize (0) ;
  159.      ptp->hbm = CreateBitmap (hab) ;                        // create bitmap
  160.  
  161.      DosEnterCritSec () ;
  162.      WinPostMsg (ptp->hwndNotify, WM_BITMAP_CREATED,        // post message
  163.                                   MPFROMP (ptp), NULL) ;
  164.      WinTerminate (hab) ;
  165.      _endthread () ;
  166.      }
  167.  
  168. HBITMAP CreateBitmap (HAB hab)
  169.      {
  170.      BITMAPINFOHEADER bmp ;
  171.      HBITMAP          hbm ;
  172.      HDC              hdcMemory ;
  173.      HPS              hpsMemory ;
  174.      LONG             alBitmapFormat[2] ;
  175.      POINTL           aptlTextBox[TXTBOX_COUNT] ;
  176.      SIZEF            sizfx ;
  177.      SIZEL            sizl ;
  178.  
  179.                               // create memory presentation space
  180.  
  181.      hdcMemory = DevOpenDC (hab, OD_MEMORY, "*", 0L, NULL, NULL) ;
  182.      sizl.cx = 0 ;
  183.      sizl.cy = 0 ;
  184.      hpsMemory = GpiCreatePS (hab, hdcMemory, &sizl,
  185.                               PU_TWIPS   | GPIF_DEFAULT |
  186.                               GPIT_MICRO | GPIA_ASSOC) ;
  187.  
  188.                               // create font, select it in PS, and size it
  189.  
  190.      CreateVectorFont (hpsMemory, LCID_FONT, FONTNAME) ;
  191.      GpiSetCharSet (hpsMemory, LCID_FONT) ;
  192.  
  193.      sizfx.cx = MAKEFIXED (XFONTSIZE * 20, 0) ;
  194.      sizfx.cy = MAKEFIXED (YFONTSIZE * 20, 0) ;
  195.      GpiSetCharBox (hpsMemory, &sizfx) ;
  196.  
  197.                               // obtain text dimensions and delete font
  198.  
  199.      GpiQueryTextBox (hpsMemory, TEXTLEN, TEXT, TXTBOX_COUNT, aptlTextBox) ;
  200.      GpiSetCharSet (hpsMemory, LCID_DEFAULT) ;
  201.      GpiDeleteSetId (hpsMemory, LCID_FONT) ;
  202.  
  203.                               // convert text dimensions to device coordinates
  204.  
  205.      sizl.cx = aptlTextBox[TXTBOX_CONCAT].x ;
  206.      sizl.cy = aptlTextBox[TXTBOX_TOPLEFT].y -
  207.                aptlTextBox[TXTBOX_BOTTOMLEFT].y ;
  208.  
  209.      GpiConvert (hpsMemory, CVTC_PAGE, CVTC_DEVICE, 1L, (PPOINTL) &sizl) ;
  210.  
  211.                               // create bitmap and set it in the PS
  212.  
  213.      GpiQueryDeviceBitmapFormats (hpsMemory, 2L, alBitmapFormat) ;
  214.  
  215.      bmp.cbFix     = 12 ;
  216.      bmp.cx        = (SHORT) sizl.cx ;
  217.      bmp.cy        = (SHORT) sizl.cy ;
  218.      bmp.cPlanes   = (SHORT) alBitmapFormat[0] ;
  219.      bmp.cBitCount = (SHORT) alBitmapFormat[1] ;
  220.  
  221.      hbm = GpiCreateBitmap (hpsMemory, &bmp, 0L, NULL, NULL) ;
  222.  
  223.                               // convert bitmap size back to page coordinates
  224.  
  225.      GpiConvert (hpsMemory, CVTC_DEVICE, CVTC_PAGE, 1L, (PPOINTL) &sizl) ;
  226.  
  227.                               // draw the text on the bitmap
  228.      if (hbm != NULL)
  229.           {
  230.           GpiSetBitmap (hpsMemory, hbm) ;
  231.           DrawImage (hpsMemory, &sizl) ;
  232.           GpiSetBitmap (hpsMemory, NULL) ;
  233.           }
  234.                               // clean up
  235.  
  236.      GpiDestroyPS (hpsMemory) ;
  237.      DevCloseDC (hdcMemory) ;
  238.  
  239.      return hbm ;
  240.      }
  241.  
  242. VOID DrawImage (HPS hps, SIZEL *psizl)
  243.      {
  244.      INT         i ;
  245.      LONG        lColor ;
  246.      POINTL      ptl, aptl[8], aptlTextBox[TXTBOX_COUNT] ;
  247.      SIZEF       sizfx ;
  248.                               // color the background
  249.  
  250.      GpiSetColor (hps, BKGNDCOLOR) ;
  251.  
  252.      ptl.x = 0 ;
  253.      ptl.y = 0 ;
  254.      GpiMove (hps, &ptl) ;
  255.  
  256.      ptl.x = psizl->cx ;
  257.      ptl.y = psizl->cy ;
  258.      GpiBox (hps, DRO_FILL, &ptl, 0L, 0L) ;
  259.  
  260.                               // create font, select it in PS, and size it
  261.  
  262.      CreateVectorFont (hps, LCID_FONT, FONTNAME) ;
  263.      GpiSetCharSet (hps, LCID_FONT) ;
  264.  
  265.      sizfx.cx = MAKEFIXED (XFONTSIZE * 20, 0) ;
  266.      sizfx.cy = MAKEFIXED (YFONTSIZE * 20, 0) ;
  267.      GpiSetCharBox (hps, &sizfx) ;
  268.  
  269.                               // create clipping path based on text outline
  270.  
  271.      GpiBeginPath (hps, ID_PATH) ;
  272.  
  273.      GpiQueryTextBox (hps, TEXTLEN, TEXT, TXTBOX_COUNT, aptlTextBox) ;
  274.      ptl.x = 0 ;
  275.      ptl.y = -aptlTextBox[TXTBOX_BOTTOMLEFT].y ;
  276.      GpiCharStringAt (hps, &ptl, TEXTLEN, TEXT) ;
  277.  
  278.      GpiEndPath (hps) ;
  279.      GpiSetClipPath (hps, ID_PATH, SCP_AND | SCP_ALTERNATE) ;
  280.  
  281.                               // switch to RGB colors
  282.  
  283.      GpiCreateLogColorTable (hps, 0L, LCOLF_RGB, 0L, 0L, NULL) ;
  284.  
  285.      for (i = 0 ; i < DIVISIONS ; i++)
  286.           {
  287.                               // set the color
  288.  
  289.           if (i < DIVISIONS / 2)
  290.                lColor = RGB (i * 512 / DIVISIONS, 0, 0) ;
  291.           else
  292.                lColor = RGB (255, i * 512 / DIVISIONS - 256,
  293.                                   i * 512 / DIVISIONS - 256) ;
  294.  
  295.           GpiSetColor (hps, lColor) ;
  296.  
  297.                               // define coordinates for spline curves
  298.  
  299.           aptl[0].x = 0 ;
  300.           aptl[0].y = i * psizl->cy / DIVISIONS ;
  301.  
  302.           aptl[1].x = psizl->cx / 4 ;
  303.           aptl[1].y = aptl[0].y + psizl->cy / 2 ;
  304.  
  305.           aptl[2].x = 3 * psizl->cx / 4 ;
  306.           aptl[2].y = aptl[0].y - psizl->cy / 2 ;
  307.  
  308.           aptl[3].x = psizl->cx ;
  309.           aptl[3].y = aptl[0].y ;
  310.  
  311.           aptl[4].x = psizl->cx ;
  312.           aptl[4].y = (i + 1) * psizl->cy / DIVISIONS ;
  313.  
  314.           aptl[5].x = 3 * psizl->cx / 4 ;
  315.           aptl[5].y = aptl[4].y - psizl->cy / 2 ;
  316.  
  317.           aptl[6].x = psizl->cx / 4 ;
  318.           aptl[6].y = aptl[4].y + psizl->cy / 2 ;
  319.  
  320.           aptl[7].x = 0 ;
  321.           aptl[7].y = aptl[4].y ;
  322.  
  323.                               // draw the curves in an area bracket
  324.  
  325.           GpiBeginArea (hps, BA_NOBOUNDARY | BA_ALTERNATE) ;
  326.  
  327.           GpiMove (hps, aptl) ;                   // set current position
  328.           GpiPolySpline (hps, 3L, aptl + 1) ;     // draw one spline
  329.           GpiLine (hps, aptl + 4) ;               // draw line
  330.           GpiPolySpline (hps, 3L, aptl + 5) ;     // draw second spline
  331.           GpiLine (hps, aptl) ;                   // line to beginning
  332.  
  333.           GpiEndArea (hps) ;
  334.           }
  335.                               // Clean up
  336.  
  337.      GpiCreateLogColorTable (hps, LCOL_RESET, LCOLF_INDRGB, 0L, 0L, NULL) ;
  338.      GpiSetCharSet (hps, LCID_DEFAULT) ;
  339.      GpiDeleteSetId (hps, LCID_FONT) ;
  340.      }
  341.  
  342. LONG CreateVectorFont (HPS hps, LONG lcid, CHAR *szFacename)
  343.      {
  344.      FATTRS fat ;
  345.                               // set up FATTRS structure
  346.  
  347.      fat.usRecordLength  = sizeof fat ;
  348.      fat.fsSelection     = 0 ;
  349.      fat.lMatch          = 0 ;
  350.      fat.idRegistry      = 0 ;
  351.      fat.usCodePage      = GpiQueryCp (hps) ;
  352.      fat.lMaxBaselineExt = 0 ;
  353.      fat.lAveCharWidth   = 0 ;
  354.      fat.fsType          = 0 ;
  355.      fat.fsFontUse       = FATTR_FONTUSE_OUTLINE |
  356.                            FATTR_FONTUSE_TRANSFORMABLE ;
  357.  
  358.      strcpy (fat.szFacename, szFacename) ;
  359.  
  360.                               // create the font
  361.  
  362.      return GpiCreateLogFont (hps, NULL, lcid, &fat) ;
  363.      }
  364.  
  365. VOID Message (HWND hwnd, SHORT sIcon, CHAR *pszMessage)
  366.      {
  367.      WinMessageBox (HWND_DESKTOP, hwnd, pszMessage, "Thread1",
  368.                     0, sIcon | MB_OK | MB_MOVEABLE) ;
  369.      }
  370.