VOID Changer_ChangerThread( VOID )
{
 // Определяем поток в системе.
 HAB Thread = WinInitialize( 0 );

 // Если это сделать не удалось - выход.
 if( Thread == NULLHANDLE )
  {
   // При создании потока произошла ошибка.
   Thread_responds.Thread_is_created = -1;

   // Выход.
   return;
  }

 // Создаем очередь сообщений - она должна быть в каждом потоке.
 HMQ Message_queue = WinCreateMsgQueue( Thread, 0 ); Enhancer.Modules.Changer->Message_queue = Message_queue;

 // Если очередь создать не удалось - выход.
 if( Enhancer.Modules.Changer->Message_queue == NULLHANDLE )
  {
   // Завершаем работу потока.
   WinTerminate( Thread );

   // При создании потока произошла ошибка.
   Thread_responds.Thread_is_created = -1;

   // Выход.
   return;
  }

 // Поток создан успешно.
 Thread_responds.Thread_is_created = 1;

 // Получение и обработка сообщений, приходящих в поток.
 QMSG Message = {0};
 while( WinGetMsg( Thread, &Message, 0, 0, 0 ) )
  {
   // Проверяем, не идет ли следом такое же сообщение.
   QMSG Next_message = {0};
   WinPeekMsg( Thread, &Next_message, NULLHANDLE, Message.msg, Message.msg, PM_NOREMOVE );
   if( Next_message.msg == Message.msg )
    if( Next_message.mp1 == Message.mp1 )
     if( Next_message.mp2 == Message.mp2 )
      if( Next_message.hwnd == Message.hwnd ) continue;

   // Обрабатываем сообщение.
   Changer_ChangerMessageProcessing( &Message );
  }

 // Завершаем работу потока.
 WinDestroyMsgQueue( Message_queue );
 WinTerminate( Thread );
 DosExit( EXIT_THREAD, 0 );
}
Esempio n. 2
0
   void ProcessWindowsMessages()
{
  QMSG qmsg;
  HAB hab;

  hab = WinInitialize(0);

  while(WinPeekMsg(hab, &qmsg, (HWND) NULL, 0, 0, PM_REMOVE))
  {
      WinDispatchMsg(hab, &qmsg);
  }
  WinTerminate(hab);
}
Esempio n. 3
0
bool
nsAppShell::ProcessNextNativeEvent(bool mayWait)
{
  bool gotMessage = false;

  do {
    QMSG qmsg;
    // Give priority to system messages (in particular keyboard, mouse, timer,
    // and paint messages).
    if (WinPeekMsg((HAB)0, &qmsg, NULL, WM_CHAR, WM_VIOCHAR, PM_REMOVE) ||
        WinPeekMsg((HAB)0, &qmsg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) || 
        WinPeekMsg((HAB)0, &qmsg, NULL, 0, WM_USER-1, PM_REMOVE) || 
        WinPeekMsg((HAB)0, &qmsg, NULL, 0, 0, PM_REMOVE)) {
      gotMessage = true;
      ::WinDispatchMsg((HAB)0, &qmsg);
    } else if (mayWait) {
      // Block and wait for any posted application message
      ::WinWaitMsg((HAB)0, 0, 0);
    }
  } while (!gotMessage && mayWait);

  return gotMessage;
}
Esempio n. 4
0
void Window::processPaint()
{
	QMSG Message;

	while( WinPeekMsg( Application::hab, &Message, hWndClient, WM_PAINT, WM_PAINT,
									   PM_REMOVE ) )
	{
    RECTL rcl;
    HPS hps = WinBeginPaint( hWndClient, NULLHANDLE, &rcl );
    Rect rect( rcl.xLeft, rcl.yBottom, rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom );
    Graphics graph( hps );
    paint( &rect, &graph );
    WinEndPaint( hps );
	}
}
Esempio n. 5
0
void Draw_Thread(ULONG ulThreadArg)
{
if(!(habDT=WinInitialize(0UL)))         /* Initialize client window */
    GEN_ERR(habDT,hwndFrame,hwndClient);
                                        /* Create a message queue */
if(!(hmqDT=WinCreateMsgQueue(habDT,0UL)))
    GEN_ERR(habDT,hwndFrame,hwndClient);
if(!(hpsDT=WinGetPS(hwndClient)))       /* Get a presentation space for client area */
    GEN_ERR(habDT,hwndFrame,hwndClient);
                                        /* Initialize message queue */
WinPostQueueMsg(hmqDT,DT_PAINT,0UL,0UL);
while(qmsqDT.msg!=DT_EXIT)
    {
    if(WinPeekMsg(habDT,                /* Get the message into message queue */
    &qmsqDT,                            /* Message structure */
    NULLHANDLE,                         /* Window filter (none) */
    0UL,                                /* First message ID */
    0UL,                                /* Last message ID */
    PM_REMOVE)==FALSE)                  /* Options (remove message) */
        qmsqDT.msg=DT_IDLE;             /* If no message available, assume idle */
    switch(qmsqDT.msg)
    {
    case DT_PAINT:                      /* Repaint client window */
        {
        RECTL   rclDT;
        int     x,y;
                                        /* Repaint client window aread */
        WinQueryWindowRect(hwndClient,&rclDT);
        WinFillRect(hpsDT,&rclDT,CLR_WHITE);
        for(x=1;x<RB_X;x++)             /* Draw the entries on playing ground */
            for(y=1;y<RB_Y;y++)
                if(RB_Array[x][y]!=RB_EMPTY)
                    Draw_Bitmap(RB_Array[x][y],ROP_SRCCOPY,(x-1)*RB_SIZE,(y-1)*RB_SIZE);
        break;
        }
    case DT_LBUTTON:
        {
        int     x,y;
                                        /* Left button was pressed, get the location,
                                           add \ to RB_Array, and draw \ bitmap, if
                                           field is emty */
        x=(LONGFROMMP(qmsqDT.mp1)/RB_SIZE)+1;
        y=(LONGFROMMP(qmsqDT.mp2)/RB_SIZE)+1;
        if(RB_Array[x][y]==RB_EMPTY)
            {
            RB_Array[x][y]=RB_LX;
            Draw_Bitmap(RB_LX,ROP_SRCCOPY,(x-1)*RB_SIZE,(y-1)*RB_SIZE);
            }
        break;
        }
    case DT_RBUTTON:
        {
        int     x,y;
                                        /* Right button was pressed, get the location,
                                           add / to RB_Array, and draw / bitmap, if
                                           field is emty */
        x=(LONGFROMMP(qmsqDT.mp1)/RB_SIZE)+1;
        y=(LONGFROMMP(qmsqDT.mp2)/RB_SIZE)+1;
        if(RB_Array[x][y]==RB_EMPTY)
            {
            RB_Array[x][y]=RB_RX;
            Draw_Bitmap(RB_RX,ROP_SRCCOPY,(x-1)*RB_SIZE,(y-1)*RB_SIZE);
            }
        break;
        }
     case DT_IDLE:
        {
        if(runRB==TRUE)
            {
            ULONG       x,y,Symbol;
                                        /* Under DOS we would query the time in milliseconds
                                           from the system timer, to adjust graphics. This
                                           is accurate, but in a multitasking in a multitasking
                                           system, we must assume being pre-empted. Therefore
                                           we can't have an exact time bases. Hope that
                                           the system timer counts more often than all 31
                                           milliseconds in future releases/machines */
                                        /* Draw bitmap */
            switch(RB_Dir)              /* Test that RollBall doesn't leave borders. A
                                           border reverses the direction and produces a
                                           beep */
            {
            case UP:
                RB_PosY++;
                if((RB_PosY+RB_SIZE)>=((RB_Y-2)*RB_SIZE))
                    {
                    RB_PosY=(RB_Y-3)*RB_SIZE;
                    RB_Dir=DOWN;
                    DosBeep(800,50);
                    }
                break;
            case DOWN:
                RB_PosY--;
                if(RB_PosY<0)
                    {
                    RB_PosY=0;
                    RB_Dir=UP;
                    DosBeep(800,50);
                    }
                break;
            case LEFT:
                RB_PosX--;
                if(RB_PosX<0)
                    {
                    RB_PosX=0;
                    RB_Dir=RIGHT;
                    DosBeep(800,50);
                    }
                break;
            case RIGHT:
                RB_PosX++;
                if((RB_PosX+RB_SIZE)>=((RB_X-2)*RB_SIZE))
                    {
                    RB_PosX=(RB_X-3)*RB_SIZE;
                    RB_Dir=LEFT;
                    DosBeep(800,50);
                    }
                break;
            }
                                        /* Draw RollBall at new position */
            Draw_Bitmap(RB_RB,ROP_SRCCOPY,RB_PosX,RB_PosY);
                                        /* Now, test if the middle of RollBall is over any
                                           symbol. If a symbol is found, add points, deflect
                                           or end game */
                                        /* RB_Array is 1 based, because 0 indices are the
                                           playing ground borders */
            x=((RB_PosX)/RB_SIZE)+1;
            y=((RB_PosY)/RB_SIZE)+1;
                                        /* A Symbol if RB_SIZE*RB_SIZE in size, that means
                                           RollBall is exactly over a symbol, if the lower
                                           left edges of both symbols match. Then, and only
                                           then, we count points, deflect or loose */
            if((RB_PosX==(x-1)*RB_SIZE) && (RB_PosY==(y-1)*RB_SIZE))
                Symbol=RB_Array[x][y];
            else Symbol=RB_EMPTY;
            switch(Symbol)
            {
            case RB_LX:                 /* We got a \ deflector */
                {
                switch(RB_Dir)          /* \ deflects direction of RollBall */
                {
                case RIGHT:
                    RB_Dir=DOWN; break;
                case UP:
                    RB_Dir=LEFT; break;
                case LEFT:
                    RB_Dir=UP; break;
                case DOWN:
                    RB_Dir=RIGHT; break;
                }                       /* Remove deflector */
                RB_Array[x][y]=RB_EMPTY;
                break;
                }
            case RB_RX:                 /* We got a / deflector */
                {
                switch(RB_Dir)          /* / deflects direction of RollBall */
                {
                case RIGHT:
                    RB_Dir=UP; break;
                case UP:
                    RB_Dir=RIGHT; break;
                case LEFT:
                    RB_Dir=DOWN; break;
                case DOWN:
                    RB_Dir=LEFT; break;
                }                       /* Remove deflector */
                RB_Array[x][y]=RB_EMPTY;
                DosBeep(600,20);
                break;
                }
            case RB_BP:                 /* We got a point */
            case RB_GP:
            case RB_MP:
            case RB_VP:
                {                       /* Add the points for each symbol */
                RB_Point[0]+=RB_Point[Symbol];
                                        /* Remove the point */
                RB_Array[x][y]=RB_EMPTY;
                if (ulDelay)
                    ulDelay--;
                DosBeep(700,20);
                break;
                }
            case RB_HOLE:               /* We got a hole, sorry but RollBall will be killed.
                                           We disable RollBall from rolling, and send a 
                                           ID_STOPTHREAD message to our window, which
                                           informs the user about the points with a message
                                           box */
                {
                int     freq;
                for(freq=5000;freq>100;freq-=100) DosBeep(freq,5);
                runRB=FALSE;            /* Prevent RollBall from further rolling */
                WinPostMsg(hwndClient,WM_COMMAND,(MPARAM)ID_STOPTHREAD,(MPARAM)0);
                break;
                }
            }
                                        /* Randomly add and remove symbols on playing ground */
            if((rand()%500)<2)
                {
                Put_Random_Field();
                Clear_Random_Field();
                }
            }
        }
    }
DosOpen("TIMER0$",
        &hfile,
        &ulAction,
        0,
        0,
        OPEN_ACTION_OPEN_IF_EXISTS,
        OPEN_FLAGS_FAIL_ON_ERROR | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE,
        NULL);   
ulDelay2=ulDelay/2;
DosDevIOCtl(hfile,
            HRT_IOCTL_CATEGORY,
            HRT_BLOCKUNTIL,
            &ulDelay2,
            ulSize2,
            &ulSize2,
            NULL,
            0,
            NULL);
DosClose(hfile);
}
WinReleasePS(hpsDT);                    /* Clean up */
WinDestroyMsgQueue(hmqDT);
WinTerminate(habDT);
DosExit(EXIT_THREAD,0UL);
}
MRESULT EXPENTRY ClientWndProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
     {
     static BOOL   fContinueCalc = FALSE ;
     static HAB    hab ;
     static HWND   hwndMenu ;
     static INT    iStatus = STATUS_READY ;
     static INT    iCurrentRep = IDM_10 ;
     static LONG   lCalcRep, lRepAmts [] = { 10, 100, 1000, 10000, 100000 } ;
     static ULONG  ulElapsedTime ;
     double        A ;
     LONG          lRep ;
     QMSG          qmsg ;

     switch (msg)
          {
          case WM_CREATE:
               hab = WinQueryAnchorBlock (hwnd) ;

               hwndMenu = WinWindowFromID (
                               WinQueryWindow (hwnd, QW_PARENT),
                               FID_MENU) ;
               return 0 ;

          case WM_COMMAND:
               switch (COMMANDMSG(&msg)->cmd)
                    {
                    case IDM_10:
                    case IDM_100:
                    case IDM_1000:
                    case IDM_10000:
                    case IDM_100000:
                         WinCheckMenuItem (hwndMenu, iCurrentRep, FALSE) ;
                         iCurrentRep = COMMANDMSG(&msg)->cmd ;
                         WinCheckMenuItem (hwndMenu, iCurrentRep, TRUE) ;
                         return 0 ;

                    case IDM_START:
                         WinEnableMenuItem (hwndMenu, IDM_START, FALSE) ;
                         WinEnableMenuItem (hwndMenu, IDM_ABORT, TRUE) ;

                         iStatus = STATUS_WORKING ;
                         WinInvalidateRect (hwnd, NULL, FALSE) ;

                         lCalcRep = lRepAmts [iCurrentRep - IDM_10] ;
                         fContinueCalc = TRUE ;
                         ulElapsedTime = WinGetCurrentTime (hab) ;

                         qmsg.msg = WM_NULL ;

                         for (A = 1.0, lRep = 0 ; lRep < lCalcRep ; lRep++)
                              {
                              A = Savage (A) ;

                              while (WinPeekMsg (hab, &qmsg, NULLHANDLE,
                                                 0, 0, PM_NOREMOVE))
                                   {
                                   if (qmsg.msg == WM_QUIT)
                                        break ;

                                   WinGetMsg (hab, &qmsg, NULLHANDLE, 0, 0) ;
                                   WinDispatchMsg (hab, &qmsg) ;

                                   if (!fContinueCalc)
                                        break ;
                                   }
                              if (!fContinueCalc || qmsg.msg == WM_QUIT)
                                   break ;
                              }
                         ulElapsedTime = WinGetCurrentTime (hab) - 
                                                  ulElapsedTime ;

                         if (!fContinueCalc || qmsg.msg == WM_QUIT)
                              iStatus = STATUS_READY ;
                         else
                              iStatus = STATUS_DONE ;

                         WinInvalidateRect (hwnd, NULL, FALSE) ;

                         WinEnableMenuItem (hwndMenu, IDM_START, TRUE) ;
                         WinEnableMenuItem (hwndMenu, IDM_ABORT, FALSE) ;
                         return 0 ;

                    case IDM_ABORT:
                         fContinueCalc = FALSE ;
                         return 0 ;
                    }
               break ;

          case WM_PAINT:
               PaintWindow (hwnd, iStatus, lCalcRep, ulElapsedTime) ;
               return 0 ;
          }
     return WinDefWindowProc (hwnd, msg, mp1, mp2) ;
     }
Esempio n. 7
0
int main( int argc, char **argv )
{
    BOOL      bOK;
    HAB       hab;
    HMQ       hmq;
    HSWITCH   hsw;
    HWND      hwndClient;
    HWND      hwndFrame;
    PGLOBALS  pg;
    QMSG      qmsg;
    SWCNTRL   swctl;
    ULONG     CtlData;
    ULONG     rc;


    hab = WinInitialize( 0 );
    hmq = WinCreateMsgQueue( hab, 0 );

    WinRegisterClass( hab, CLASSNAME, ClientWinProc, CS_SIZEREDRAW, sizeof( PGLOBALS ) );

    // create invisible
    CtlData = FCF_SYSMENU | FCF_TITLEBAR | FCF_SIZEBORDER | FCF_MINMAX |  FCF_MENU | FCF_ICON;
    hwndFrame = WinCreateStdWindow( HWND_DESKTOP, 0, &CtlData, CLASSNAME, CAPTION, 0, (HMODULE)0, ID_PMPGM, &hwndClient );

#ifdef DEBUG
    pmassert( hab, hwndFrame );
#endif

    // get global pointer stored by wm_create processing
    pg = (PGLOBALS) WinQueryWindowULong( hwndClient, QWL_USER );

#ifdef DEBUG
    pmassert( hab, pg );
#endif

    // store my msg queue handle in there
    pg->hmq = hmq;

    // set position of minimized mshell window
    bOK = WinSetWindowUShort( pg->hwndFrame, QWS_XMINIMIZE, (USHORT)pg->profile.swpMinimized.x );

#ifdef DEBUG
    pmassert( hab, bOK );
#endif

    bOK = WinSetWindowUShort( pg->hwndFrame, QWS_YMINIMIZE, (USHORT)pg->profile.swpMinimized.y );

#ifdef DEBUG
    pmassert( hab, bOK );
#endif

    // use profiled placement for restored size
    rc = WinSetWindowPos( pg->hwndFrame,
                          (HWND)0,
                          pg->profile.swp.x,
                          pg->profile.swp.y,
                          pg->profile.swp.cx,
                          pg->profile.swp.cy,
                          SWP_SIZE | SWP_MOVE | SWP_ACTIVATE );

#ifdef DEBUG
    pmassert( hab, rc );
#endif

    // add program to task list
    memset( &swctl, 0, sizeof( SWCNTRL ));
    strcpy( swctl.szSwtitle, CAPTION    );
    swctl.hwnd          = hwndFrame;
    swctl.uchVisibility = SWL_VISIBLE;
    swctl.fbJump        = SWL_JUMPABLE;
    hsw = WinAddSwitchEntry( &swctl );

    // make it visible
    WinShowWindow( pg->hwndFrame, TRUE );

    // use break statement to get out of this message loop
    for(;;) {

#if 1
        // until I call winshutdownsystem, toss out quit messages
        if( ! pg->fShutdownCalled ) {
            WinPeekMsg( hab, &qmsg, 0, WM_QUIT, WM_QUIT, PM_REMOVE );
        }

        if( WinGetMsg( hab, &qmsg, 0, 0, 0 )) {
            WinDispatchMsg( hab, &qmsg );
        } else break;
#endif

#if 0
        WinGetMsg( hab, &qmsg, 0, 0, 0 );
        WinDispatchMsg( hab, &qmsg );
#endif

    }

    // wrap up
    WinRemoveSwitchEntry( hsw );
    WinDestroyWindow ( hwndFrame );
    WinDestroyMsgQueue ( hmq );
    WinTerminate ( hab );

    return 0;
}
Esempio n. 8
0
MRESULT EXPENTRY fnwpReadColumnClient(HWND hwnd,USHORT msg,MPARAM mp1,MPARAM mp2)
  {
  static HDC hdcPs;
  RECTL   rclRect;
  POINTL ptl;
  LONG lSaveEdge;
  SWP swp;
  HWND hwndMenu;
  static USHORT usMenuStyle;
  static CLRDLG stColor;
  static USHORT usLastPopupItem;

  switch(msg)
    {
    case WM_CHAR:
      if (bSendNextKeystroke)
        if (ProcessKeystroke(&stCFG,mp1,mp2))
          return((MRESULT)TRUE);
      return( WinDefWindowProc(hwnd,msg,mp1,mp2));
    case WM_CREATE:
      hdcPs = WinOpenWindowDC(hwnd);
      usLastPopupItem = IDMPU_SYNC;
      stRead.lBackgrndColor = stCFG.lReadColBackgrndColor;
      stRead.bActive = FALSE;
      stRead.lScrollIndex = 0;
      stRead.hwndScroll = (HWND)NULL;
      stRead.wDirection = CS_READ;
      stColor.cbSize = sizeof(CLRDLG);
      usMenuStyle = (PU_POSITIONONITEM | PU_MOUSEBUTTON2 | PU_HCONSTRAIN | PU_VCONSTRAIN | PU_KEYBOARD | PU_MOUSEBUTTON1);
      WinSendMsg(hwnd,UM_TRACKFRAME,0L,0L);
      break;
    case WM_ACTIVATE:
      if(SHORT1FROMMP(mp1))
        {
        if (!bFrameActivated)
          {
          WinSetFocus(HWND_DESKTOP,hwndFrame);
          WinSendMsg(WinQueryHelpInstance(hwndClient),HM_SET_ACTIVE_WINDOW,0L,0L);
          bFrameActivated = TRUE;
          }
        }
      else
        bFrameActivated = FALSE;
      break;
    case WM_VSCROLL:
      switch(HIUSHORT(mp2))
        {
        case SB_LINEDOWN:
          ColScroll(&stRead,1,FALSE);
          break;
        case SB_LINEUP:
          ColScroll(&stRead,-1,FALSE);
          break;
        case SB_PAGEDOWN:
          ColScroll(&stRead,stRead.lCharHeight,FALSE);
          break;
        case SB_PAGEUP:
          ColScroll(&stRead,-stRead.lCharHeight,FALSE);
          break;
        case SB_SLIDERPOSITION:
          ColScroll(&stRead,LOUSHORT(mp2),TRUE);
          break;
        }
      break;
    case WM_COMMAND:
      switch (SHORT1FROMMP(mp1))
        {
        case IDMPU_ASCII_FONT:
          if (!stCFG.bStickyMenus)
            usLastPopupItem = IDMPU_FONT;
          else
            usLastPopupItem = IDMPU_SYNC;
          if (stCFG.wColReadFont != wASCIIfont)
            {
            stCFG.wColReadFont = wASCIIfont;
            WinInvalidateRect(stRead.hwndClient,(PRECTL)NULL,FALSE);
            }
          break;
        case IDMPU_HEX_FONT:
          if (!stCFG.bStickyMenus)
            usLastPopupItem = IDMPU_FONT;
          else
            usLastPopupItem = IDMPU_SYNC;
          if (stCFG.wColReadFont != wHEXfont)
            {
            stCFG.wColReadFont = wHEXfont;
            WinInvalidateRect(stRead.hwndClient,(PRECTL)NULL,FALSE);
            }
          break;
        case IDMPU_SYNC:
          usLastPopupItem = IDMPU_SYNC;
          if (bStopDisplayThread)
            stRead.lScrollIndex = stWrite.lScrollIndex;
          else
            stRead.lScrollIndex = 0;
          stRead.lScrollRow = GetColScrollRow(&stRead,0);
          WinSendMsg(stRead.hwndScroll,
                     SBM_SETPOS,
                     MPFROMSHORT(stRead.lScrollRow),
                     MPFROMSHORT(0));
          if (stRead.bSync)
            {
            stRow.lScrollIndex = stRead.lScrollIndex;
            stRow.lScrollRow = GetRowScrollRow(&stRow);
            }
          WinInvalidateRect(stRead.hwndClient,(PRECTL)NULL,FALSE);
          break;
         case IDMPU_COLORS:
          if (!stCFG.bStickyMenus)
            usLastPopupItem = IDMPU_COLORS;
          else
            usLastPopupItem = IDMPU_SYNC;
          stColor.lForeground = stCFG.lReadColForegrndColor;
          stColor.lBackground = stCFG.lReadColBackgrndColor;
          sprintf(stColor.szCaption,"Lexical Receive Data Display Colors");
          if (WinDlgBox(HWND_DESKTOP,
                        hwnd,
                 (PFNWP)fnwpSetColorDlg,
                (USHORT)NULL,
                        CLR_DLG,
                MPFROMP(&stColor)))
            {
            stCFG.lReadColForegrndColor = stColor.lForeground;
            stCFG.lReadColBackgrndColor = stColor.lBackground;
            stRead.lBackgrndColor = stColor.lBackground;
            stRead.lForegrndColor = stColor.lForeground;
            WinInvalidateRect(stRead.hwndClient,(PRECTL)NULL,FALSE);
            }
          break;
        case IDMPU_LOCK_WIDTH:
          if (!stCFG.bStickyMenus)
            usLastPopupItem = IDMPU_LOCK_WIDTH;
          else
            usLastPopupItem = IDMPU_SYNC;
          if (stCFG.fLockWidth == LOCK_READ)
            stCFG.fLockWidth = LOCK_NONE;
          else
            {
            stCFG.lLockWidth = ((stRead.lWidth / stCell.cx) + 1);
            stCFG.fLockWidth = LOCK_READ;
            }
          break;
        case IDMPU_DISP_FILTERS:
          if (!stCFG.bStickyMenus)
            usLastPopupItem = IDMPU_DISP_FILTERS;
          else
            usLastPopupItem = IDMPU_SYNC;
          if (WinDlgBox(HWND_DESKTOP,
                        hwnd,
                 (PFNWP)fnwpDisplaySetupDlgProc,
                (USHORT)NULL,
                        DISP_FILTER_DLG,
                MPFROMP(&stRead)))
            {
            stCFG.bReadTestNewLine = stRead.bTestNewLine;
            stCFG.bSkipReadBlankLines = stRead.bSkipBlankLines;
            stCFG.byReadNewLineChar = stRead.byNewLineChar;
            stCFG.bFilterRead = stRead.bFilter;
            stCFG.fFilterReadMask = stRead.fFilterMask;
            stCFG.byReadMask = stRead.byDisplayMask;
            if (stRead.bSync)
              {
              if (!stCFG.bSyncToRead)
                {
                stWrite.bSync = FALSE;
                stCFG.bSyncToWrite = FALSE;
                stCFG.bSyncToRead = TRUE;
                if (stCFG.fDisplaying & (DISP_DATA | DISP_FILE))
                  {
                  ClearColScrollBar(&stWrite);
                  SetupColScrolling(&stRead);
                  }
                }
              }
            else
              {
              if (stCFG.bSyncToRead)
                {
                stCFG.bSyncToRead = FALSE;
                if (stCFG.fDisplaying & (DISP_DATA | DISP_FILE))
                  SetupColScrolling(&stWrite);
                }
              }
            WinInvalidateRect(stRead.hwndClient,(PRECTL)NULL,FALSE);
            }
          break;
        }
      break;
//    case WM_CHORD:
    case WM_BUTTON2DOWN:
      if(bFrameActivated)
        {
        hwndMenu = WinLoadMenu(stRead.hwnd,(HMODULE)NULL,IDMPU_COL_DISP_POPUP);
        if (mp1 != 0)
          {
          WinQueryPointerPos(HWND_DESKTOP,&ptl);
          if (!stCFG.bStickyMenus)
            usMenuStyle |= PU_MOUSEBUTTON2DOWN;
          else
            usMenuStyle &= ~PU_MOUSEBUTTON2DOWN;
          }
        else
          {
          usMenuStyle &= ~PU_MOUSEBUTTON2DOWN;
          WinQueryWindowPos(hwndFrame,&swp);
          ptl.x = (swp.x + (swp.cx - (swp.cx / 4)));
          ptl.y = (swp.y + (swp.cy / 2));
          }
        if (stCFG.wColReadFont == wASCIIfont)
          PopupMenuItemCheck(hwndMenu,IDMPU_ASCII_FONT,TRUE);
        else
          PopupMenuItemCheck(hwndMenu,IDMPU_HEX_FONT,TRUE);
        if (stCFG.fLockWidth == LOCK_READ)
          PopupMenuItemCheck(hwndMenu,IDMPU_LOCK_WIDTH,TRUE);
        if (!bStopDisplayThread)
          WinSendMsg(hwndMenu,MM_SETITEMTEXT,(MPARAM)IDMPU_SYNC,"~Reset Display");
        WinPopupMenu(HWND_DESKTOP,stRead.hwndClient,hwndMenu,ptl.x,ptl.y,usLastPopupItem,usMenuStyle);
        }
      else
        return WinDefWindowProc(hwnd,msg,mp1,mp2);
      break;
    case WM_BUTTON1DOWN:
      if(bFrameActivated)
        {
        WinCopyRect(habAnchorBlock,&rclRect,&stRead.rcl);
        lSaveEdge = rclRect.xLeft;
        if (TrackChildWindow(habAnchorBlock,hwndClient,&rclRect,TF_LEFT))
          {
          if (rclRect.xLeft != lSaveEdge)
            {
            WinSendMsg(stWrite.hwndClient,UM_TRACKSIB,0L,(MPARAM)rclRect.xLeft);
            WinSendMsg(stRead.hwndClient,UM_TRACKSIB,(MPARAM)rclRect.xLeft,0L);
            if (stCFG.fLockWidth == LOCK_WRITE)
              stCFG.lLockWidth = ((stWrite.lWidth / stCell.cx) + 1);
            else
              stCFG.lLockWidth = ((stRead.lWidth / stCell.cx) + 1);
            }
          }
        }
      else
        return WinDefWindowProc(hwnd,msg,mp1,mp2);
      break;
    case WM_DESTROY:
      GpiDestroyPS(hdcPs);
      break;
    case UM_SHOWNEW:
      stRead.lScrollIndex = 0;
      stRead.lScrollRow = 0;
      ClearColScrollBar(&stRead);
    case UM_SHOWAGAIN:
      stRead.bActive = TRUE;
      if ((stCFG.fDisplaying & (DISP_DATA | DISP_FILE)) && !stCFG.bSyncToWrite)
        SetupColScrolling(&stRead);
      WinShowWindow(stRead.hwnd,TRUE);
      WinSendMsg(hwnd,UM_TRACKFRAME,0L,0L);
      WinInvalidateRect(stRead.hwndClient,(PRECTL)NULL,FALSE);
      WinInvalidateRect(hwndStatus,(PRECTL)NULL,FALSE);
      break;
    case UM_HIDEWIN:
      ClearColScrollBar(&stRead);
      stRead.bActive = FALSE;
      WinShowWindow(hwnd,FALSE);
      WinSetWindowPos(stRead.hwnd,HWND_BOTTOM,0L,0L,0L,0L,(SWP_MOVE | SWP_SIZE | SWP_ZORDER));
      break;
    case WM_PAINT:
#ifdef this_junk
      if (!pstCFG->bDisplayingData && (stCFG.bSyncToRead || stCFG.bSyncToWrite))
        ColumnPaint(&stRead,WinPeekMsg(habAnchorBlock,&stQmsg,stWrite.hwndClient,WM_PAINT,WM_PAINT,PM_REMOVE));
      else
#endif
        ColumnPaint(&stRead);
      break;
    case UM_TRACKSIB:
      ColumnSize(&stRead,(LONG)mp1,(LONG)mp2,TRUE);
      break;
    case UM_TRACKFRAME:
      ColumnSize(&stRead,(LONG)mp1,(LONG)mp2,FALSE);
      break;
    case WM_ERASEBACKGROUND:
      return (MRESULT)(TRUE);
    case WM_CLOSE:
      WinPostMsg(hwnd,WM_QUIT,0L,0L);
    default:
      return WinDefWindowProc(hwnd,msg,mp1,mp2);
    }
  return(FALSE);
  }
// Message определяет пришедшее сообщение. Thread - поток.
VOID Painter_PainterMessageProcessing( PQMSG Message, HAB Thread )
{
 // Устанавливаем приоритет потока.
 if( Message->msg == SM_PRIORITY )
  {
   // Устанавливаем приоритет.
   LONG Class = (LONG) Message->mp1;
   LONG Delta = (LONG) Message->mp2;
   DosSetPriority( PRTYS_THREAD, Class, Delta, 0 );

   // Запоминаем приоритет.
   Enhancer.Modules.Painter->Priority = MAKELONG( Class, Delta );
  }

 // Перерисовываем рамки окон.
 if( Message->msg == SM_DRAW_FRAME )
  {
   // Если рисование отключено - возврат.
   if( !Painter.Settings.Draw_frames ) return;

   // Кеш второго уровня: объединяем несколько заданий в одно.
   {
    // Ставим задание в список.
    Painter.RTSettings.Demand[ 0 ].Frame_window = (HWND) Message->mp1;
    Painter.RTSettings.Demand[ 0 ].Target = (ULONG) Message->mp2;

    // Забираем следующие задания из очереди и ставим их в список.
    INT Demand_total = 1;

    for( INT Count = 1; Count < PAINTER_DEMAND_TABLE; Count ++ )
     {
      QMSG Next_message = {0};
      WinPeekMsg( Thread, &Next_message, NULLHANDLE, SM_DRAW_FRAME, SM_DRAW_FRAME, PM_REMOVE );

      if( Next_message.msg )
       {
        Painter.RTSettings.Demand[ Count ].Frame_window = (HWND) Next_message.mp1;
        Painter.RTSettings.Demand[ Count ].Target = (ULONG) Next_message.mp2;

        Demand_total ++;
       }
      else
       {
        break;
       }
     }

    // Просматриваем составленный список и выполняем рисование.
    for( Count = 0; Count < Demand_total; Count ++ )
     {
      // Узнаем окно рамки.
      HWND Frame_window = Painter.RTSettings.Demand[ Count ].Frame_window;
      // Если в списке нет значения - продолжаем перебор.
      if( Frame_window == NULLHANDLE ) continue;

      // Узнаем, какое окно надо перерисовать.
      ULONG Target = Painter.RTSettings.Demand[ Count ].Target;

      // Пробегаем список до конца и забираем задания для того же окна.
      if( Demand_total > 1 )
       if( Count != Demand_total - 1 )
        {
         for( INT Position = Count + 1; Position < Demand_total; Position ++ )
          if( Painter.RTSettings.Demand[ Position ].Frame_window == Frame_window )
           {
            Target = Target | Painter.RTSettings.Demand[ Position ].Target;
            Painter.RTSettings.Demand[ Position ].Frame_window = NULLHANDLE;
           }
        }

      // Если окна нет - продолжаем перебор.
      if( !WinIsWindow( WinQueryAnchorBlock( Frame_window ), Frame_window ) ) continue;

      // Перерисовываем рамку, применяя "общее задание".
      Painter_DrawWindowFrame( Frame_window, Target );
     }
   }
  }

 // Перерисовываем картинку в левом верхнем углу окна.
 if( Message->msg == SM_DRAW_SYSMENU )
  {
   // Если рисование отключено - возврат.
   if( !Painter.Settings.Draw_frames ) return;

   // Узнаем окно картинки.
   HWND SysMenu_window = (HWND) Message->mp1;

   // Если окна нет - возврат.
   if( !WinIsWindow( WinQueryAnchorBlock( SysMenu_window ), SysMenu_window ) ) return;

   // Узнаем, нажата ли картинка.
   LONG SysMenu_is_pressed = (LONG) Message->mp2;

   // Находим в списке значок окна.
   HPOINTER Icon = NULLHANDLE;
   HWND Frame_window = WinQueryWindow( SysMenu_window, QW_PARENT );

   FindProperty( Frame_window, PRP_ICON, &Icon );

   // Узнаем размер и расположение окна рамки.
   RECT Frame_rectangle = {0}; SWP Frame_placement = {0};
   Painter_QueryFrameRectangeAndPlacement( Frame_window, &Frame_rectangle, &Frame_placement );

   // Если значок не найден - закрашиваем окно картинки.
   if( Icon == NULLHANDLE ) Painter_PreDrawControl( SysMenu_window, SYSCLR_BUTTONMIDDLE, 0, Frame_window, &Frame_rectangle, &Frame_placement );
   // Иначе - рисуем картинку.
   else Painter_DrawSystemMenu( SysMenu_window, Frame_window, &Frame_rectangle, &Frame_placement, Icon, FT_UNKNOWN, SysMenu_is_pressed );
  }

 // Перерисовываем кнопки.
 if( Message->msg == SM_DRAW_BUTTONS )
  {
   // Если рисование отключено - возврат.
   if( !Painter.Settings.Draw_frames ) return;

   // Узнаем окно рамки.
   HWND Frame_window = (HWND) Message->mp1;

   // Если окна рамки нет - возврат.
   if( !WinIsWindow( WinQueryAnchorBlock( Frame_window ), Frame_window ) ) return;

   // Узнаем, как выглядит рамка окна.
   LONG Frame_type = FrameType( Frame_window );

   // Узнаем окно заголовка.
   HWND TitleBar_window = WinWindowFromID( Frame_window, FID_TITLEBAR );

   // Узнаем размер и расположение окна рамки.
   RECT Frame_rectangle = {0}; SWP Frame_placement = {0};
   Painter_QueryFrameRectangeAndPlacement( Frame_window, &Frame_rectangle, &Frame_placement );

   // Рисуем кнопки.
   Painter_DrawButtons( Frame_window, Frame_type, &Frame_rectangle, &Frame_placement, TitleBar_window );
  }

 // Задаем подходящее расположение для окна картинки и кнопок.
 if( Message->msg == SM_PREPARE_CONTROLS )
  {
   // Узнаем окно рамки.
   HWND Frame_window = (HWND) Message->mp1;

   // Если окна рамки нет - возврат.
   if( !WinIsWindow( WinQueryAnchorBlock( Frame_window ), Frame_window ) ) return;

   // Узнаем размер и расположение окна.
   RECT Frame_rectangle = {0}; SWP Frame_placement = {0};
   Painter_QueryFrameRectangeAndPlacement( Frame_window, &Frame_rectangle, &Frame_placement );

   // Задаем правильное расположение окна картинки, заголовка и других окон.
   // При этом окно рамки получит одно сообщение WM_PAINT вместо нескольких.
   Painter_PrepareWindowControls( Frame_window, FT_UNKNOWN, &Frame_rectangle, &Frame_placement, NULLHANDLE, NULLHANDLE, NULLHANDLE );
  }

 // Обновляем окно.
 if( Message->msg == SM_UPDATE_FRAME ) UpdateWindow( (HWND) Message->mp1 );

 // Обновляем все окна.
 if( Message->msg == SM_UPDATE_ALL_FRAMES )
  {
   // Перерисовываем рамки всех окон.
   UpdateAllWindows( QueryDesktopWindow() );
  }

 // Возврат.
 return;
}