BOOL APIENTRY WprogressBar(HWND hParent, HWND hOwner, PPROGRESSDLG ppd) { QMSG qmsg; HWND hwnd; PPRGSAPPDATA pad; BOOL rc = FALSE; // allocate storage for application data if (!(pad = (PPRGSAPPDATA)malloc(sizeof(PRGSAPPDATA)))) return FALSE; memset(pad, 0, sizeof(PRGSAPPDATA)); pad->ppd = ppd; // ottiene tempo di inizio pad->start = WinGetCurrentTime(pad->hab = WinQueryAnchorBlock(hOwner)) / 1000; // window handles if (ppd->fl & PRGSS_BITMAP) { SIZEL szl; WqueryBitmapSize(pad->ppd->hbmp, &szl); pad->cxbmp = szl.cx; } /* endif */ if (NULLHANDLE != (hwnd = WinLoadDlg(hParent, hOwner, ProgressDlgProc, hmod, DLG_PROGRESS, pad))) { if (!ppd->pszPrgrss) ppd->pszPrgrss = SZ_PROGRESS; if (!ppd->pszTime) ppd->pszTime = SZ_ELAPSTIME; if (ppd->pszStop) WinSetDlgItemText(hwnd, BTN_STOP, ppd->pszStop); pad->hOwner = WinQueryWindow(hwnd, QW_OWNER); WinEnableWindow(pad->hOwner, FALSE); for(;;) { if (WinGetMsg(pad->hab, &qmsg, NULLHANDLE, 0, 0)) { // loop standard if (qmsg.msg == PRGSM_END && qmsg.hwnd == hwnd) { if (pad->qQuit.msg) WinPostMsg(pad->qQuit.hwnd, pad->qQuit.msg, pad->qQuit.mp1, pad->qQuit.mp2); break; } // end if WinDispatchMsg(pad->hab, &qmsg); } else { // WM_QUIT pad->qQuit = qmsg; if(qmsg.hwnd == NULLHANDLE) // SHUTDOWN WinPostMsg(hwnd, WM_CLOSE, MPFROMLONG(TRUE), NULL); else if(qmsg.hwnd == HWNDFROMMP(qmsg.mp2)) // TASKLIST WinPostMsg(hwnd, WM_CLOSE, 0L, 0L); else // chiusura regolare: termina break; } // end if } // end forever WinSetFocus(HWND_DESKTOP, hOwner); WinDestroyWindow(hwnd); WinEnableWindow(pad->hOwner, TRUE); rc = TRUE; } // end if free(pad); return rc; }
MRESULT EXPENTRY ProgressDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) { switch (msg) { // init ----------------------------------------------------------------- case WM_INITDLG: { PPRGSAPPDATA pad = (PPRGSAPPDATA)mp2; ULONG ul; POINTL aptl[] = {{1, 36}, {220, 24}}; WinSetWindowPtr(hwnd, 0L, (PVOID)mp2); WinSetWindowText(hwnd, pad->ppd->pszTitle); // dimensioni-coordinate varie pad->cyTitle = uGetSval(SV_CYTITLEBAR); pad->hButton = WinWindowFromID(hwnd, BTN_STOP); WinQueryWindowPos(pad->hButton, &pad->swp); WinQueryWindowRect(hwnd, &pad->rcl); WinMapDlgPoints(hwnd, aptl, 2, TRUE); pad->sldd.cbSize = sizeof(SLDCDATA); pad->sldd.usScale1Increments = 11; pad->sldd.usScale1Spacing = (pad->rcl.xRight - 2 * pad->cyTitle) / 10 - 1; pad->hProgress = WinCreateWindow(hwnd, WC_SLIDER, (PSZ)NULL, SLS_BOTTOM | SLS_OWNERDRAW | SLS_READONLY | SLS_RIBBONSTRIP | WS_VISIBLE, 3, aptl[0].y, pad->rcl.xRight - 6, aptl[1].y, hwnd, HWND_TOP, SLDR_PROGRESS, (PVOID)&pad->sldd, NULL); // controlla versione S.O. e setta font slider e bottone DosQuerySysInfo(QSV_VERSION_MINOR, QSV_VERSION_MINOR, &ul, sizeof(ULONG)); if (ul < 40) { WinSetPresParam(pad->hProgress, PP_FONTNAMESIZE, 7, "8.Helv"); WinSetPresParam(pad->hButton, PP_FONTNAMESIZE, 7, "8.Helv"); } else { WinSetPresParam(pad->hProgress, PP_FONTNAMESIZE, 11, "9.WarpSans"); } /* endif */ // rileva larghezza progress bar pad->cxPrgs = LOUSHORT((ULONG)WinSendMsg(pad->hProgress, SLM_QUERYSLIDERINFO, MPFROM2SHORT(SMA_SHAFTDIMENSIONS, 0), MPVOID)) - 6; // setta altezza barra pari a altezza barra titolo WinSendMsg(pad->hProgress, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SHAFTDIMENSIONS, 0), (MPARAM)pad->cyTitle); // setta testo e altezza barra graduata WinSendMsg(pad->hProgress, SLM_SETTICKSIZE, MPFROM2SHORT(SMA_SETALLTICKS, pad->cyTitle / 3), MPVOID); WinSendMsg(pad->hProgress, SLM_SETSCALETEXT, (MPARAM)0, (MPARAM)"0%"); WinSendMsg(pad->hProgress, SLM_SETSCALETEXT, (MPARAM)5, (MPARAM)"50%"); WinSendMsg(pad->hProgress, SLM_SETSCALETEXT, (MPARAM)10, (MPARAM)"100%"); // testo iniziale progesso e elapsed time: sprintf(pad->achElapsed, "%s: 00:00:00", pad->ppd->pszTime); WinSetDlgItemText(hwnd, TXT_TIME, pad->achElapsed); sprintf(pad->achCurPrg, "%s: 0%%", pad->ppd->pszPrgrss); WinSetDlgItemText(hwnd, TXT_PERCENT, pad->achCurPrg); // se specificato setta nuovo font dialogo if (pad->ppd->fl & PRGSS_FONT) WsetDlgFonts(hwnd, NULLHANDLE, pad->ppd->FontNameSize); // posiziona finestra al centro Parent window if (pad->ppd->fl & PRGSS_CENTER) { WcenterInWindow(hwnd, pad->ppd->hPos); } else { SWP swp; swp.hwnd = pad->ppd->hPos; swp.x = pad->ppd->ptl.x; swp.y = pad->ppd->ptl.y; swp.cx = swp.cy = 0; swp.fl = SWP_MOVE | SWP_SHOW | SWP_ACTIVATE | SWP_ZORDER; swp.hwndInsertBehind = HWND_TOP; WsetRelativePos(hwnd, &swp); } // end if // notifica creazione dialogo WinPostMsg(pad->ppd->hNotify, WM_PRGRSREADY, (MPARAM)hwnd, (MPARAM)0); break; } // end case WM_INITDLG case WM_DRAWITEM: if (((POWNERITEM)mp2)->idItem == SDA_RIBBONSTRIP) { PPRGSAPPDATA pad = GetData(hwnd); if (pad->ppd->fl & PRGSS_BITMAP) { // se deve disegnare la bitmap RECTL rcl = {0, 0, ((POWNERITEM)mp2)->rclItem.xRight - ((POWNERITEM)mp2)->rclItem.xLeft, pad->cyTitle}; POINTL ptl = {((POWNERITEM)mp2)->rclItem.xLeft, ((POWNERITEM)mp2)->rclItem.yBottom}; while (ptl.x < ((POWNERITEM)mp2)->rclItem.xRight) { WinDrawBitmap(((POWNERITEM)mp2)->hps, pad->ppd->hbmp, &rcl, &ptl, 0L, 0L, DBM_NORMAL); ptl.x += pad->cxbmp; rcl.xRight = ((POWNERITEM)mp2)->rclItem.xRight - ptl.x; } /* endwhile */ } else { // colore GpiCreateLogColorTable(((POWNERITEM)mp2)->hps, 0, LCOLF_RGB, 0, 0, NULL); WinFillRect(((POWNERITEM)mp2)->hps, &((POWNERITEM)mp2)->rclItem, pad->ppd->color); } /* endif */ return (MRESULT)TRUE; } // end if break; case PRGSM_INCREMENT: { // notifica incremento PPRGSAPPDATA pad = GetData(hwnd); ULONG ul; pad->incr = (ULONG)mp1; WinSendMsg(pad->hProgress, SLM_SETSLIDERINFO, MPFROM2SHORT(SMA_SLIDERARMPOSITION, SMA_RANGEVALUE), (MPARAM)((pad->incr * pad->cxPrgs) / 1000)); ul = WinGetCurrentTime(pad->hab) / 1000; if (pad->current != ul) { pad->current = ul; pad->elapsed = pad->current - pad->start; sprintf(pad->achElapsed, "%s: %02d:%02d:%02d", pad->ppd->pszTime, pad->elapsed / 3600, (pad->elapsed % 3600) / 60, pad->elapsed % 60); WinSetDlgItemText(hwnd, TXT_TIME, pad->achElapsed); } // end if if (pad->ulCurPrg != (ul = (ULONG)mp1 / 10)) { pad->ulCurPrg = ul; sprintf(pad->achCurPrg, "%s: %3d %%", pad->ppd->pszPrgrss, pad->ulCurPrg); WinSetDlgItemText(hwnd, TXT_PERCENT, pad->achCurPrg); } // end if return (MRESULT)pad->flStop; } // end case PRGSM_INCREMENT case PRGSM_MSG: return (MRESULT)Wprint(hwnd, (PSZ)mp1, (ULONG)mp2); case WM_COMMAND: if ((ULONG)mp1 == BTN_STOP) { PPRGSAPPDATA pad = GetData(hwnd); pad->flStop = TRUE; WinEnableWindow(pad->hButton, FALSE); } /* endif */ break; case WM_CLOSE: { PPRGSAPPDATA pad = GetData(hwnd); // se elaborazione ancora in corso mostra messaggio if (pad->incr > 0 && pad->incr < 1000) { PSZ psz; if (!(psz = (PSZ)malloc(1024)) || // se la notify window restituisce NULL (BOOL)WinSendMsg(pad->ppd->hNotify, WM_PRGRSQUIT, (MPARAM)psz, MPVOID) || // o se la chiusura Š confermata Wprint(hwnd, psz, PMPRNT_QUERY)) { WinPostMsg(hwnd, PRGSM_END, MPVOID, MPVOID); WinPostMsg(pad->hOwner, WM_CLOSE, MPVOID, MPVOID); // se nel frattempo Š terminato } else { pad->qQuit.msg = 0; if (!pad->incr || pad->incr >= 1000) { WinPostMsg(hwnd, PRGSM_END, MPVOID, MPVOID); } else if ((BOOL)mp1) { WinCancelShutdown((HMQ)WinQueryWindowULong(hwnd, QWL_HMQ), FALSE); } // end if } // end if free (psz); } /* endif */ } break; default: return WinDefDlgProc(hwnd, msg, mp1, mp2); } /* endswitch */ return (MRESULT)FALSE; }
MRESULT Window::stdWndProc( HWND hWnd, ULONG iMessage, MPARAM mParam1, MPARAM mParam2, BOOL *returned ) { switch( iMessage ) { // case WM_FOCUSCHANGE : case WM_SETSELECTION : case WM_ACTIVATE : { if( type != Window::LISTBOX && type != Window::COMBOLISTBOX ) { focus( (BOOL)mParam1 );//SHORT1FROMMP( mParam2 ) ); } break; } case WM_SETFOCUS : { if( type != Window::LISTBOX && type != Window::COMBOLISTBOX ) focusSet( (BOOL)mParam2 ); break; } case WM_BUTTON1DOWN : { if( type == SCROLLBAR ) setFocus(); HWND hwnd = WinQueryFocus( HWND_DESKTOP ); if( mouseListener.getSize() != 0 ) { mouseButtonDown = TRUE; WinSetCapture( HWND_DESKTOP, hWnd ); WinStartTimer( Application::hab, hWndClient, 1, 50 ); Point pos( SHORT1FROMMP(mParam1), SHORT2FROMMP(mParam1) ); performMouseEvent( &pos, AMouseEvent::LEFT, AMouseEvent::DOWN ); } if( hwnd != WinQueryFocus( HWND_DESKTOP ) ) return (MRESULT)TRUE; break; } case WM_BUTTON1UP : { if( type == LISTBOX || type == COMBOLISTBOX ) { performFocusEvent( (int)WinSendMsg( (HWND)mParam2, LM_QUERYSELECTION, MPARAM(0), MPARAM(NULL) ) ); } else if( mouseListener.getSize() != 0 ) { mouseButtonDown = FALSE; WinStopTimer( Application::hab, hWndClient, 1 ); WinSetCapture( HWND_DESKTOP, NULLHANDLE ); Point pos( SHORT1FROMMP(mParam1), SHORT2FROMMP(mParam1) ); performMouseEvent( &pos, AMouseEvent::LEFT, AMouseEvent::RELEASE ); // return (MPARAM)TRUE; } break; } case WM_BUTTON2DOWN : { if( mouseListener.getSize() != 0 ) { WinSetCapture( HWND_DESKTOP, hWnd ); WinStartTimer( Application::hab, hWndClient, 1, 50 ); Point pos( SHORT1FROMMP(mParam1), SHORT2FROMMP(mParam1) ); performMouseEvent( &pos, AMouseEvent::RIGHT, AMouseEvent::DOWN ); } break; } case WM_BUTTON2UP : { if( mouseListener.getSize() != 0 ) { WinStopTimer( Application::hab, hWndClient, 1 ); WinSetCapture( HWND_DESKTOP, NULLHANDLE ); Point pos( SHORT1FROMMP(mParam1), SHORT2FROMMP(mParam1) ); performMouseEvent( &pos, AMouseEvent::RIGHT, AMouseEvent::RELEASE ); } break; } case WM_BUTTON1CLICK : { if( mouseListener.getSize() != 0 ) { // Check if triple click int newTick = WinGetCurrentTime( Application::hab ); if( newTick - lastTick <= WinQuerySysValue( HWND_DESKTOP, SV_DBLCLKTIME ) ) { Point pos( SHORT1FROMMP(mParam1), SHORT2FROMMP(mParam1) ); performMouseEvent( &pos, AMouseEvent::LEFT, AMouseEvent::TRIPLECLICK ); } else { Point pos( SHORT1FROMMP(mParam1), SHORT2FROMMP(mParam1) ); performMouseEvent( &pos, AMouseEvent::LEFT, AMouseEvent::CLICK ); } } break; } case WM_BUTTON2CLICK : { if( mouseListener.getSize() != 0 ) { Point pos( SHORT1FROMMP(mParam1), SHORT2FROMMP(mParam1) ); performMouseEvent( &pos, AMouseEvent::RIGHT, AMouseEvent::CLICK ); } break; } case WM_BUTTON1DBLCLK : { if( mouseListener.getSize() != 0 ) { Point pos( SHORT1FROMMP(mParam1), SHORT2FROMMP(mParam1) ); performMouseEvent( &pos, AMouseEvent::LEFT, AMouseEvent::DOUBLECLICK ); } lastTick = WinGetCurrentTime( Application::hab ); break; } case WM_BUTTON2DBLCLK : { if( mouseListener.getSize() != 0 ) { Point pos( SHORT1FROMMP(mParam1), SHORT2FROMMP(mParam1) ); performMouseEvent( &pos, AMouseEvent::RIGHT, AMouseEvent::DOUBLECLICK ); } break; } case WM_MOUSEMOVE : { if( currentPointer != NULLHANDLE ) WinSetPointer( HWND_DESKTOP, currentPointer ); if( mouseListener.getSize() != 0 ) { Point pos( (SHORT)SHORT1FROMMP(mParam1), (SHORT)SHORT2FROMMP(mParam1) ); performMouseEvent( &pos, 0, AMouseEvent::MOVE ); } if( currentPointer != NULLHANDLE ) return (MPARAM)TRUE; break; } case WM_TIMER : { if( mouseButtonDown ) { POINTL ptl; WinQueryPointerPos( HWND_DESKTOP, &ptl ); WinMapWindowPoints( HWND_DESKTOP, hWnd, &ptl, 1 ); if( ptl.y < 0 || ptl.y > height ) { Point pos( ptl.x, ptl.y ); performMouseEvent( &pos, 0, AMouseEvent::MOVE ); } } break; } case WM_SIZE : { int oldWidth = width, oldHeight = height; SWP swp; WinQueryWindowPos( hWndFrame, &swp ); width = swp.cx; height = swp.cy; size( oldWidth, oldHeight ); break; } case WM_HSCROLL : { int pos = SHORT1FROMMP( mParam2 ), id = SHORT1FROMMP( mParam1 ); switch( SHORT2FROMMP( mParam2 ) ) { case SB_PAGERIGHT : { performScrollbarEvent( id, Scrollbar::PAGERIGHT, pos ); break; } case SB_PAGELEFT : { performScrollbarEvent( id, Scrollbar::PAGELEFT, pos ); break; } case SB_LINERIGHT : { performScrollbarEvent( id, Scrollbar::LINERIGHT, pos ); break; } case SB_LINELEFT : { performScrollbarEvent( id, Scrollbar::LINELEFT, pos ); break; } case SB_SLIDERTRACK : { performScrollbarEvent( id, Scrollbar::HORZTRACK, pos ); break; } case SB_SLIDERPOSITION : { performScrollbarEvent( id, Scrollbar::HORZRELEASED, pos ); break; } } break; } case WM_SYSCOMMAND : { // Check if the parent is a dialog, then chain the WM_SYSCOMMAND if( parent->getType() == DIALOG ) WinSendMsg( ((Window *)parent)->getHWND(), WM_SYSCOMMAND, mParam1, mParam2 ); break; } case WM_VSCROLL : { int id = SHORT1FROMMP( mParam1 ); Scrollbar *scrollbar = (Scrollbar *)getControl( id ); int pos; if( scrollbar ) pos = scrollbar->convertScrollPosToReal( SHORT1FROMMP( mParam2 ) ); else pos = SHORT1FROMMP( mParam2 ); switch( SHORT2FROMMP( mParam2 ) ) { case SB_PAGEDOWN : { performScrollbarEvent( id, Scrollbar::PAGEDOWN, pos ); break; } case SB_PAGEUP : { performScrollbarEvent( id, Scrollbar::PAGEUP, pos ); break; } case SB_LINEDOWN : { performScrollbarEvent( id, Scrollbar::LINEDOWN, pos ); break; } case SB_LINEUP : { performScrollbarEvent( id, Scrollbar::LINEUP, pos ); break; } case SB_SLIDERTRACK : { performScrollbarEvent( id, Scrollbar::VERTTRACK, pos ); break; } case SB_SLIDERPOSITION : { performScrollbarEvent( id, Scrollbar::VERTRELEASED, pos ); break; } } break; } case WM_MOVE : { SWP swp; WinQueryWindowPos( hWndFrame, &swp ); x = swp.x; y = swp.y; move(); break; } case WM_CLOSE : { if( close() ) break; else return (MPARAM)FALSE; } case WM_COMMAND : { if( SHORT1FROMMP( mParam2 ) == CMDSRC_PUSHBUTTON ) { Window *control = (Window *)getControl( SHORT1FROMMP(mParam1)); if( control != NULL ) { if( control->type == PUSHBUTTON ) { control->performButtonEvent( control, control->id ); return FALSE; } } else return FALSE; // In case ESC would close the dialog } break; } case WM_CHAR : { if( type == LISTBOX ) { performFocusEvent( (int)WinSendMsg( (HWND)mParam2, LM_QUERYSELECTION, MPARAM(0), MPARAM(NULL) ) ); } if( (SHORT1FROMMP( mParam1 ) & KC_KEYUP) || (SHORT1FROMMP( mParam1 ) & KC_DEADKEY) || (SHORT1FROMMP( mParam1 ) & KC_INVALIDCOMP) ) break; /* if( SHORT1FROMMP( mParam1 ) & KC_COMPOSITE ) mParam1 = MPFROM2SHORT( SHORT1FROMMP( mParam1 ) & ~KC_VIRTUALKEY, SHORT2FROMMP( mParam1 ) );*/ int modifiers = 0; if( SHORT1FROMMP( mParam1 ) & KC_SHIFT ) modifiers |= KeyDef::SHIFT; if( SHORT1FROMMP( mParam1 ) & KC_ALT ) modifiers |= KeyDef::kALT; if( SHORT1FROMMP( mParam1 ) & KC_CTRL) modifiers |= KeyDef::CTRL; if( SHORT1FROMMP( mParam1 ) & KC_VIRTUALKEY ) { int key = 0, vKey = SHORT2FROMMP( mParam2 ); // Maybe NumLock is on if( SHORT1FROMMP(mParam1) & KC_CHAR && !(vKey == VK_ENTER || vKey == VK_NEWLINE || vKey == VK_TAB || vKey == VK_BACKSPACE )) key = SHORT1FROMMP( mParam2 ); else if( vKey == VK_UP ) key = KeyDef::UP; else if( vKey == VK_DOWN ) key = KeyDef::DOWN; else if( vKey == VK_LEFT ) key = KeyDef::LEFT; else if( vKey == VK_RIGHT ) key = KeyDef::RIGHT; else if( vKey == VK_PAGEUP ) key = KeyDef::PAGEUP; else if( vKey == VK_PAGEDOWN ) key = KeyDef::PAGEDOWN; else if( vKey == VK_INSERT ) key = KeyDef::INSERT; else if( vKey == VK_DELETE ) key = KeyDef::kDELETE; else if( vKey == VK_HOME ) key = KeyDef::HOME; else if( vKey == VK_END ) key = KeyDef::END; else if( vKey == VK_ESC ) key = KeyDef::ESCAPE; else if( vKey == VK_F1 ) key = KeyDef::F1; else if( vKey == VK_F2 ) key = KeyDef::F2; else if( vKey == VK_F3 ) key = KeyDef::F3; else if( vKey == VK_F4 ) key = KeyDef::F4; else if( vKey == VK_F5 ) key = KeyDef::F5; else if( vKey == VK_F6 ) key = KeyDef::F6; else if( vKey == VK_F7 ) key = KeyDef::F7; else if( vKey == VK_F8 ) key = KeyDef::F8; else if( vKey == VK_F9 ) key = KeyDef::F9; else if( vKey == VK_F10 ) key = KeyDef::F10; else if( vKey == VK_F11 ) key = KeyDef::F11; else if( vKey == VK_F12 ) key = KeyDef::F12; else if( vKey == VK_ENTER ) key = KeyDef::ENTER; else if( vKey == VK_NEWLINE ) key = KeyDef::RETURN; else if( vKey == VK_BACKSPACE ) key = KeyDef::BACKSPACE; else if( vKey == VK_TAB ) key = KeyDef::TAB; else if( vKey == VK_BACKTAB ) { key = KeyDef::TAB; modifiers |= KeyDef::SHIFT; } else if( vKey == VK_SPACE ) key = KeyDef::SPACE; if( parent->getType() == DIALOG ) ((Dialog *)parent)->focusHotkey( key ); if( key != 0 ) if( performKeyEvent( this, modifiers, key ) ) return MPARAM(TRUE); // Do not pass up and down key to dialog if this is a combobox (would // move focus) /* if( getFilterDialogArrows() && (vKey == VK_UP || vKey == VK_DOWN) ) return (MPARAM)TRUE;*/ } else { int key = SHORT1FROMMP( mParam2 ); if( performKeyEvent( this, modifiers, key ) ) return MPARAM(TRUE); } break; } case WM_CONTROL : { Window *control = (Window *)getControl( SHORT1FROMMP(mParam1)); if( control != NULL ) { if( control->type == Window::LISTBOX || control->type == Window::COMBOLISTBOX ) { switch( SHORT2FROMMP(mParam1) ) { case LN_KILLFOCUS : control->focus( FALSE ); break; case LN_SETFOCUS : control->focus( TRUE );break; case LN_ENTER : control->performSelectionEvent( (int)WinSendMsg( (HWND)mParam2, LM_QUERYSELECTION, MPARAM(0), MPARAM(NULL) ) ); break; } } else if( control->type == Window::SCROLLBAR ) { switch( SHORT2FROMMP(mParam1) ) { case SLN_KILLFOCUS : control->focus( FALSE ); break; case SLN_SETFOCUS : control->setFocus(); break; } } else if( control->type == Window::RADIOBUTTON || control->type == Window::CHECKBOX ) { switch( SHORT2FROMMP( mParam1) ) { case BN_CLICKED : case BN_DBLCLICKED : control->performButtonEvent( control, control->id ); break; } } } break; } case DM_DRAGOVER: { PDRAGINFO pDInfo; PDRAGITEM pDItem; if( !acceptDropFiles ) return MRFROM2SHORT(DOR_NODROPOP, 0); pDInfo = (PDRAGINFO)mParam1; DrgAccessDraginfo(pDInfo); pDItem = DrgQueryDragitemPtr(pDInfo, 0); USHORT usOp = 0, usDrop = DOR_NEVERDROP; /* Inspect each item to see if it is acceptable */ ULONG ulItems = DrgQueryDragitemCount (pDInfo); for (INT i = 0; i < ulItems; i++) { pDItem = DrgQueryDragitemPtr(pDInfo, i); /* The item is acceptable only if it is copyable and the */ /* operation is a copy, or it is moveable and the operation */ /* is a move, and it can render <DRM_OS2FILE, NULL> */ if (pDItem->fsSupportedOps & DO_COPYABLE) { usOp = DO_COPY; /* Only check files, all types */ if (DrgVerifyRMF(pDItem, "DRM_OS2FILE", 0)) usDrop = DOR_DROP; else { usDrop = DOR_NEVERDROP; break; } } else { /* Must be a file but not droppable in type op */ usDrop = DOR_NODROPOP; usOp = 0; break; } } /* end for all items dragged */ DrgFreeDraginfo(pDInfo); return MRFROM2SHORT(usDrop, usOp); } case DM_DROP: { PDRAGINFO pDInfo; PDRAGITEM pDItem; pDInfo = (PDRAGINFO)mParam1; DrgAccessDraginfo(pDInfo); pDItem = DrgQueryDragitemPtr(pDInfo, 0); ULONG ulItems = DrgQueryDragitemCount (pDInfo); ULONG p; char **files; files = (char **)malloc( sizeof( char * ) * ulItems ); for (INT i=0; i < ulItems; i++) { CHAR DragSrcPath[CCHMAXPATH], DragSrcName[CCHMAXPATH]; pDItem = DrgQueryDragitemPtr(pDInfo, i); DrgQueryStrName(pDItem->hstrContainerName, sizeof(DragSrcPath), (PSZ)DragSrcPath); if (!(PSZ)DragSrcPath) break; if (DragSrcPath[(strlen(DragSrcPath)-1)] != '\\') strcat((PSZ)DragSrcPath, "\\"); /* Use the dragitem source name, it's the real name */ DrgQueryStrName(pDItem->hstrSourceName, sizeof(DragSrcName), (PSZ)DragSrcName); if (!((PSZ)DragSrcName)) break; strcat((PSZ)DragSrcPath, (PSZ)DragSrcName); FILESTATUS3 fsFile; DosError(FERR_DISABLEHARDERR); APIRET rc = DosQueryPathInfo(DragSrcPath, FIL_STANDARD, &fsFile, sizeof(FILESTATUS3)); DosError(FERR_ENABLEHARDERR); if (!rc && !(fsFile.attrFile & FILE_DIRECTORY)) { files[i] = (char *)malloc( strlen(DragSrcPath) + 1 ); strcpy( files[i], DragSrcPath ); DrgSendTransferMsg(pDItem->hwndItem, DM_ENDCONVERSATION, MPFROMLONG(pDItem->ulItemID), MPFROMLONG(DMFL_TARGETSUCCESSFUL)); } else { DosBeep(100,10); // EditorDisplay[BufNum]->DisplayMessage( pszDropNoFile ); } } filesDropped( files, ulItems ); for( i = 0; i < ulItems; i++ ) free( (void *)files[i] ); free( (void *)files ); DrgFreeDraginfo(pDInfo); break; } case WM_USER + 1 : { return (MPARAM)execFromMainThread( (int)mParam1, (void *)mParam2 ); } case WM_USER + 2 : { setFocus(); break; } } *returned = FALSE; return (MRESULT)NULL; }
MRESULT EXPENTRY WndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2 ) { // static POINTS DragStartPtrPos; POINTL ptl; static char Row, Col; static BOOL HasMoved = FALSE; static BOOL IntroSoundPlayed = FALSE; static BOOL RealPaint = TRUE; // indicates whether the board // has to be repainted or just copied INT aktscan; CHAR msgtext[256]; ULONG ulResponse; // ERRORID errId; switch( msg ){ case WM_CREATE: if( !InfoData.LoadHigh() ){ // get previously saved highscores InfoData.ResetHigh(); WinMessageBox( HWND_DESKTOP, hwndMain, "The file scores.dat " \ "(which is in the current directory) was somehow corrupted." \ " All Highscores will be reset to Zero.", "Error when loading Highscores", 0, MB_OK | MB_INFORMATION ); } // allocate memory for global variables; see GLOBALS struct in tgraph.h pg = new GLOBALS; // initialize globals to zero memset( pg, 0, sizeof( GLOBALS )); // store globals pointer into client window words; see WinRegisterClass // WinSetWindowULong( hwnd, QWL_USER, (ULONG) pg ); wcprintf("1: %x", WinGetLastError( hab ) ); DosCreateEventSem( NULL, &hevWaitAfterScan, 0, FALSE ); // Sem is created in reset state DosCreateEventSem( NULL, &hevHiScoreWin, 0, FALSE ); DosCreateEventSem( NULL, &hevWaitAfterSound, 0, FALSE ); DosCreateEventSem( NULL, &hevWaitSoundReady, 0, TRUE ); // Sem is created in posted state // hevWaitAfterScan and hewWaitAfterSound are used to indicate // when the respective WM_CREATE routines are done. // after that they are in posted state, as desired // initialize globals with important data pg->hab = hab; pg->hwndClient = hwnd; pg->hwndFrame = WinQueryWindow( hwnd, QW_PARENT ); pg->hwndTitlebar = WinWindowFromID( pg->hwndFrame, FID_TITLEBAR ); pg->hwndMenubar = WinWindowFromID( pg->hwndFrame, FID_MENU ); // create graphics and sound threads pg->tidTSound = _beginthread( &threadsound, NULL, LEN_STACK, NULL ); pg->tidTGraph = _beginthread( &threadgraph, NULL, LEN_STACK, NULL ); DosWaitEventSem( hevWaitAfterSound, SEM_INDEFINITE_WAIT ); WinPostMsg( pg->hwndTSound, WM_SOUND_INTRO, MPFROMHWND(hwnd), 0 ); // wait for the sound's WM_CREATE DosWaitEventSem( hevWaitAfterScan, SEM_INDEFINITE_WAIT ); // wait for the graphics' WM_CREATE InfoData.ShipsNotFound = GBoard.GetShipNumber(); wcprintf("create: %x", WinGetLastError( hab ) ); return (MRESULT)0; case WM_CONTROL: break; case WM_QUIT: break; case WM_CLOSE: // this message is sent before WM_QUIT InfoData.SaveHigh( WinGetCurrentTime(hab) ); // save the highscores and provide a random seed // get pointer to globals from window words // pg = (PGLOBALS) WinQueryWindowULong( hwnd, QWL_USER ); // tell object windows to quit, then exit their threads // WinSendMsg( pg->hwndTGraph, WM_DESTROY, mp1, mp2 ); WinPostMsg( pg->hwndTGraph, WM_QUIT, mp1, mp2 ); // WinSendMsg( pg->hwndTSound, WM_DESTROY, mp1, mp2 ); WinPostMsg( pg->hwndTSound, WM_QUIT, mp1, mp2 ); DosCloseEventSem( hevWaitAfterScan ); DosCloseEventSem( hevHiScoreWin ); DosCloseEventSem( hevWaitAfterSound ); DosCloseEventSem( hevWaitSoundReady ); WriteProfile( hab ); delete pg; return (MRESULT) 0; case WM_ERASEBACKGROUND: wcprintf("erasebackground"); // return (MRESULT) FALSE; return (MRESULT) TRUE; case WM_PAINT: /////////////////////////////////// { RECTL rectl; WinQueryWindowRect( pg->hwndClient, &rectl ); wcprintf("Linienrechteck: Breite: %d H”he: %d", rectl.xRight, rectl.yTop ); // test size: GpiSetColor( hpsGlob, CLR_RED ); ptl.x = rectl.xLeft; ptl.y = rectl.yBottom; GpiMove( hpsGlob, &ptl ); ptl.x = rectl.xRight; ptl.y = rectl.yTop; GpiLine( hpsGlob, &ptl ); } /////////////////////////// break; case WM_SIZE: wcprintf("main wnd function wm-size"); RealPaint = TRUE; GBoard.SetPMBoardValues( SHORT1FROMMP( mp2 ), SHORT2FROMMP( mp2 ) ); WndResize( hwnd ); wcprintf("size: %x", WinGetLastError( hab ) ); break; case WM_BEGINDRAG: WinSetCapture( HWND_DESKTOP, hwnd ); // capture the mouse pointer GBoard.SetfDrag( TRUE ); // indicate that mouse is being dragged GBoard.ResetFirstDraw(); // for initialization of drag op. fHideSquare = TRUE; WinSendMsg( pg->hwndTGraph, WM_SHOWPOINTERPOS, MPFROMHWND(hwnd), MPFROM2SHORT( 0, 0 ) ); // GBoard.ShowPointerPos( hwnd, 0, 0 ); // removes the square ptl.x = SHORT1FROMMP(mp1); ptl.y = SHORT2FROMMP(mp1); Row = GBoard.GetBoardRow( ptl.y ); // starting point of drag Col = GBoard.GetBoardCol( ptl.x ); // operation; static! return (MRESULT)TRUE; case WM_MOUSEMOVE: if( GBoard.GetfDrag() ){ // if mouse is being dragged WinSendMsg( pg->hwndTGraph, WM_DRAWDRAGLINE, mp1, MPFROM2SHORT( Row, Col ) ); HasMoved = TRUE; } else { // mouse is moved normally if( !fHideSquare ) WinSendMsg( pg->hwndTGraph, WM_SHOWPOINTERPOS, MPFROMHWND(hwnd), mp1 ); // GBoard.ShowPointerPos( hwnd, SHORT1FROMMP(mp1), // SHORT2FROMMP(mp1)); } break; case WM_ENDDRAG: WinSetCapture( HWND_DESKTOP, NULLHANDLE ); // release the captured // mouse pointer if( HasMoved ){ // mousemove has actually been moved WinSendMsg( pg->hwndTGraph, WM_MARKDRAGLINE, MPFROM2SHORT( Row, Col ), 0 ); HasMoved = FALSE; } GBoard.SetfDrag( FALSE ); GBoard.ClearDrawPoint(); // because no square is drawn right now fHideSquare = FALSE; WinSendMsg( pg->hwndTGraph, WM_SHOWPOINTERPOS, MPFROMHWND(hwnd), mp1 ); // GBoard.ShowPointerPos( hwnd, SHORT1FROMMP(mp1), SHORT2FROMMP(mp1)); // draws square at the current ptr pos break; case WM_CHAR: // key was pressed if( SHORT2FROMMP( mp2 ) != VK_SPACE ) break; // only space is interesting if( GBoard.GetfDrag() ) break; // do nothing while dragging if( !GBoard.GetfShowLines() ){ // lines not visible yet GBoard.SetfShowLines( TRUE ); WinSendMsg( pg->hwndTGraph, WM_DISPLAYLINES, 0, 0 ); } break; case WM_BUTTON1CLICK: if( !InfoData.ShipsNotFound ) break; // game is finished ptl.x = (LONG)SHORT1FROMMP( mp1 ); ptl.y = (LONG)SHORT2FROMMP( mp1 ); Row = GBoard.GetBoardRow( ptl.y ); Col = GBoard.GetBoardCol( ptl.x ); if( !Row || !Col ) break; fHideSquare = TRUE; WinSendMsg( pg->hwndTGraph, WM_SHOWPOINTERPOS, MPFROMHWND(hwnd), MPFROM2SHORT( 0, 0 ) ); // GBoard.ShowPointerPos( hwnd, 0, 0 ); // hides pointer square if(( aktscan = GBoard.GetDiscovered( Row, Col )) != -1 ){ WinSendMsg( pg->hwndTGraph, WM_DRAWPMPLACE, MPFROMHWND(hwnd), MPFROMSH2CH( MAKESHORT(Row, Col), (CHAR)aktscan,(CHAR)TRUE)); // umstricken auf WinPostMsg // toggle Place display } else { // scan Place DosResetEventSem( hevWaitAfterScan, &ulResponse ); // DosBeep(500, 150 ); WinPostMsg( pg->hwndTGraph, WM_GRAPH_SCAN, MPFROMHWND(hwnd), MPFROM2SHORT( Row, Col ) ); // DosBeep( 800, 150 ); WinWaitEventSem( hevWaitAfterScan, SEM_INDEFINITE_WAIT ); // DosBeep( 1000, 150 ); // first the scanning sounds must be played (and finished) aktscan = GBoard.Scan( Row, Col ); if( aktscan == GBoard.GetShipNumber() + 10 ){ InfoData.ShipsNotFound--; WinPostMsg( pg->hwndTSound, WM_SOUND_FOUNDSHIP, MPFROMHWND(hwnd), 0 ); } else { if( aktscan ) WinPostMsg( pg->hwndTSound, WM_SOUND_FOUND, MPFROMHWND(hwnd), MPFROMLONG( aktscan ) ); else WinPostMsg( pg->hwndTSound, WM_SOUND_FOUND0, MPFROMHWND(hwnd), 0 ); } WinWaitEventSem( hevWaitAfterScan, SEM_INDEFINITE_WAIT ); // waits until scanning is done, and only then displays the // field icon // hps = WinGetPS( hwnd ); WinSendMsg( pg->hwndTGraph, WM_DRAWPMPLACE, MPFROMHWND(hwnd), MPFROMSH2CH( MAKESHORT(Row, Col), (CHAR)aktscan,(CHAR)TRUE)); // umstricken auf WinPostMsg WinPostMsg( pg->hwndTGraph, WM_SHOWSTATUSLINE, 0, 0 ); // ShowStatusLine( hps, GBoard.MovesNeeded(), InfoData.ShipsNotFound, // GBoard.GetWinWidth(), GBoard.GetWinHeight() ); // WinReleasePS( hps ); if( !InfoData.ShipsNotFound ){ // game is finished, all ships found Score = GBoard.MovesNeeded(); if ( !InfoData.ReturnLastHigh() // still space in the hiscore table || Score < InfoData.ReturnLastHigh() ){ // player kicks last one out // player enters highscore table WinPostMsg( pg->hwndTSound, WM_SOUND_NEWHISCORE, MPFROMHWND(hwnd), 0 ); WinWaitEventSem( hevHiScoreWin, SEM_INDEFINITE_WAIT ); // waits until the NEWHISCORE sound is actually played WinDlgBox( HWND_DESKTOP, hwnd, HighScoreDlgProc, (HMODULE)0, IDR_HIGHSCOREDLG, NULL ); WinPostMsg( hwnd, WM_COMMAND, MPFROMSHORT(IDM_GAMEHIGH), (MPARAM)0 ); // show highscore-table DosResetEventSem( hevHiScoreWin, &ulResponse ); // resets the sem again } else { WinPostMsg( pg->hwndTSound, WM_SOUND_LOST, MPFROMHWND(hwnd), 0 ); WinWaitEventSem( hevHiScoreWin, SEM_INDEFINITE_WAIT ); // waits until the NEWHISCORE sound is actually played sprintf( msgtext, "You needed %d moves to find the lost ships. " \ "To enter the highscore list you need %d moves." \ " So try again!", Score, InfoData.ReturnLastHigh() - 1 ); WinMessageBox( HWND_DESKTOP, hwnd, msgtext, "Oh, Shit!", 0, MB_OK | MB_INFORMATION | MB_HELP ); } } } fHideSquare = FALSE; WinSendMsg( pg->hwndTGraph, WM_SHOWPOINTERPOS, MPFROMHWND(hwnd), MPFROM2SHORT( ptl.x, ptl.y ) ); // GBoard.ShowPointerPos( hwnd, ptl.x, ptl.y ); // redisplay ptr square break; case WM_BUTTON2CLICK: fHideSquare = TRUE; WinSendMsg( pg->hwndTGraph, WM_SHOWPOINTERPOS, MPFROMHWND(hwnd), MPFROM2SHORT( 0, 0 ) ); ptl.x = (LONG)SHORT1FROMMP( mp1 ); ptl.y = (LONG)SHORT2FROMMP( mp1 ); Row = GBoard.GetBoardRow( ptl.y ); Col = GBoard.GetBoardCol( ptl.x ); WinSendMsg( pg->hwndTGraph, WM_DRAWPMMARK, MPFROMHWND(hwnd), MPFROM2SHORT( Row, Col ) ); fHideSquare = FALSE; WinSendMsg( pg->hwndTGraph, WM_SHOWPOINTERPOS, MPFROMHWND(hwnd), MPFROM2SHORT( ptl.x, ptl.y ) ); break; case WM_COMMAND: switch( SHORT1FROMMP( mp1 ) ){ case IDM_GAMENEW: GBoard.NewGame(); InfoData.ShipsNotFound = GBoard.GetShipNumber(); RealPaint = TRUE; WinInvalidateRect( hwnd, NULL, TRUE ); break; case IDM_GAMESETTINGS: if( WinDlgBox( HWND_DESKTOP, hwndFrame, GameSettingsDlgProc, (HMODULE)0, IDR_GAMESETTINGSDLG, NULL ) ){ // screen must be repainted RealPaint = TRUE; WinInvalidateRect( hwnd, NULL, TRUE ); } break; case IDM_GAMEHIGH: if( !WinDlgBox( HWND_DESKTOP, hwndFrame, ShowHighDlgProc, (HMODULE)0, IDR_SHOWHIGHDLG, NULL ) ){ // user requested "Clear" if( WinMessageBox( HWND_DESKTOP, hwndMain, "Do you really want to eradicate all those " \ "arduously achieved highscores?", "Clear Highscores", 0, MB_OKCANCEL | MB_WARNING ) == MBID_OK ) InfoData.ResetHigh(); } break; case IDM_HELPINDEX: // help index WinSendMsg( hwndHelp, HM_HELP_INDEX, 0, 0 ); break; case IDM_HELPGENERAL: // general help WinSendMsg( hwndHelp, HM_EXT_HELP, 0, 0 ); break; case IDM_HELPEXTENDED: // help on help (system page) WinSendMsg( hwndHelp, HM_DISPLAY_HELP, 0, 0 ); break; case IDM_HELPKEYS: // keys help WinSendMsg( hwndHelp, HM_KEYS_HELP, 0, 0 ); break; case IDM_HELPPRODUCTINFO: ulResponse = WinDlgBox( HWND_DESKTOP, hwndFrame, ProdInfoDlgProc, (HMODULE)0, IDR_PRODINFODLG, NULL ); break; } break; case HM_QUERY_KEYS_HELP: // system asks which page to display return MRFROMSHORT( PANEL_HELPKEYS ); case HM_HELPSUBITEM_NOT_FOUND: return (MRESULT)FALSE; case WM_USER_ACK: // graphics task finished its work // DosBeep( 1000, 150 ); switch( (ULONG)mp1 ){ case WM_USER_PAINT: WinQueryPointerPos( HWND_DESKTOP, &ptl ); WinMapWindowPoints( HWND_DESKTOP, hwnd, &ptl, 1); fHideSquare = FALSE; WinSendMsg( pg->hwndTGraph, WM_SHOWPOINTERPOS, MPFROMHWND(hwnd), MPFROM2SHORT( ptl.x, ptl.y ) ); // GBoard.ShowPointerPos( hwnd, ptl.x, ptl.y ); // painting has finished, square can be displayed now break; } break; case WM_SOUND_ACK: switch( (ULONG)mp1 ){ case WM_SOUND_INTRO: break; } break; default: return (MRESULT)WinDefWindowProc( hwnd, msg, mp1, mp2 ); } // end switch( msg ) return (MRESULT)WinDefWindowProc( hwnd, msg, mp1, mp2 ); } // end MRESULT EXPENTRY WndProc()
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) ; }
void draw_thread(void *args) { static long b,b2,index; static int distance; static RECTL ScreenSize; static long Color; static DATETIME DateTime; static POINTL p1,p2,op1,op2; static POINTL ptl[3]; static long width,height; static long starcount,whiteStars,redStars,blueStars,yellowStars; static POINTL *whitesegs,*redsegs,*bluesegs,*yellowsegs; static POINTL *whitesegs_o,*redsegs_o,*bluesegs_o,*yellowsegs_o; static long x[500],y[500]; static float realX[500],realY[500],realZ[500],sx[500],sy[500],sz[500],size[500]; static float ss,dfx,dfy,dfz,dd,f; static long whitecount,redcount,bluecount,yellowcount; static long whitecount_o,redcount_o,bluecount_o,yellowcount_o; static long wc,rc,bc,yc; static long gravity; static float middleX,middleY,middleZ; int first; POINTL whitesegsAr[200]; POINTL redsegsAr[200]; POINTL bluesegsAr[200]; POINTL yellowsegsAr[200]; POINTL whitesegsAr_o[200]; POINTL redsegsAr_o[200]; POINTL bluesegsAr_o[200]; POINTL yellowsegsAr_o[200]; long gridX,gridY; long gridX_o,gridY_o; int isGrid; int inside; long searchNearX; long searchNearY; float dsx; float dsy; float ds; float minds; char starName[MAX_NAMESIZE]; char starName_o[MAX_NAMESIZE]; BOOL tracename; BOOL trid; float sinA; float cosA; float yAxis1Mx,yAxis1My,yAxis1Mz; float yAxis2Mx,yAxis2My,yAxis2Mz; float xAxis1Mx,xAxis1My,xAxis1Mz; float xAxis2Mx,xAxis2My,xAxis2Mz; float zAxis1Mx,zAxis1My,zAxis1Mz; float zAxis2Mx,zAxis2My,zAxis2Mz; float yAr1x,yAr1y,yAr1z; float yAr2x,yAr2y,yAr2z; float xAr1x,xAr1y,xAr1z; float xAr2x,xAr2y,xAr2z; float zAr1x,zAr1y,zAr1z; float zAr2x,zAr2y,zAr2z; long yAxis12Dx,yAxis12Dy; long yAxis22Dx,yAxis22Dy; long xAxis12Dx,xAxis12Dy; long xAxis22Dx,xAxis22Dy; long zAxis12Dx,zAxis12Dy; long zAxis22Dx,zAxis22Dy; long yAr12Dx,yAr12Dy; long yAr22Dx,yAr22Dy; long xAr12Dx,xAr12Dy; long xAr22Dx,xAr22Dy; long zAr12Dx,zAr12Dy; long zAr22Dx,zAr22Dy; HAB drawingthread_hab = WinInitialize(0); HMQ drawingthread_hmq = WinCreateMsgQueue(drawingthread_hab, 0); /* Settings galaxy parameter. */ setTNGfont(hps); /* Setzen der Schriftart */ whiteStars=configuration_data.whitestar_count; redStars=configuration_data.redstar_count; blueStars=configuration_data.bluestar_count; yellowStars=configuration_data.yellowstar_count; tracename=configuration_data.tracename; gravity=configuration_data.gravity; starcount=whiteStars+redStars+blueStars+yellowStars; width = screenSizeX; height = screenSizeY; trid=configuration_data.show3d; sinA=sin(-0.03f); cosA=cos(-0.03f); if ( trid ) { yAxis1Mx= 0; yAxis1My=AXISMY; yAxis1Mz= 0; yAxis2Mx= 0; yAxis2My=AXISMY+AXISL; yAxis2Mz= 0; yAr1x= ARROWW; yAr1y= AXISMY+AXISL-ARROWL; yAr1z= 0; yAr2x= -ARROWW; yAr2y= AXISMY+AXISL-ARROWL; yAr2z= 0; xAxis1Mx=-AXISL2; xAxis1My=AXISMY; xAxis1Mz= 0; xAxis2Mx=AXISL2; xAxis2My=AXISMY; xAxis2Mz= 0; xAr1x= AXISL2-ARROWL; xAr1y= AXISMY; xAr1z= ARROWW; xAr2x= AXISL2-ARROWL; xAr2y= AXISMY; xAr2z= -ARROWW; zAxis1Mx= 0; zAxis1My=AXISMY; zAxis1Mz=-AXISL2; zAxis2Mx= 0; zAxis2My=AXISMY; zAxis2Mz=AXISL2; zAr1x= ARROWW; zAr1y= AXISMY; zAr1z= AXISL2-ARROWL; zAr2x= -ARROWW; zAr2y= AXISMY; zAr2z= AXISL2-ARROWL; convertTo2D(yAxis1Mx,yAxis1My,yAxis1Mz,&yAxis12Dx,&yAxis12Dy); convertTo2D(yAxis2Mx,yAxis2My,yAxis2Mz,&yAxis22Dx,&yAxis22Dy); } /* random seed (needed for each thread) */ srand(WinGetCurrentTime(hab)); /* Clear the background. */ WinQueryWindowRect( hwndSaver, &ScreenSize ); WinFillRect( hps, &ScreenSize, CLR_BLACK ); /* Allocate memory. */ /* whitesegs = (POINTL *) ( malloc ( sizeof ( POINTL ) * starcount * 4 ) ); redsegs = (POINTL *) ( malloc ( sizeof ( POINTL ) * starcount * 4 ) ); bluesegs = (POINTL *) ( malloc ( sizeof ( POINTL ) * starcount * 4 ) ); yellowsegs = (POINTL *) ( malloc ( sizeof ( POINTL ) * starcount * 4 ) ); */ whitesegs = (POINTL *) &whitesegsAr; redsegs = (POINTL *) &redsegsAr; bluesegs = (POINTL *) &bluesegsAr; yellowsegs =(POINTL *) &yellowsegsAr; whitesegs_o = (POINTL *) &whitesegsAr_o; redsegs_o = (POINTL *) &redsegsAr_o; bluesegs_o = (POINTL *) &bluesegsAr_o; yellowsegs_o =(POINTL *) &yellowsegsAr_o; /* Init stars */ for (b = 0; b < starcount; b++) { if (trid) { realX[b] = (rand()%(4000))-2000; realY[b] = (rand()%(2000))-1000; realZ[b] = (rand()%(4000))-2000; } else { realX[b] = (rand()%(4000))-2000; realY[b] = (rand()%(4000))-2000; realZ[b] = 0; } size[b]=1; if ( rand()%(10)>7 ) { size[b]=4; } sx[b]=0; sy[b]=0; sz[b]=0; x[b]=-1; y[b]=-1; } first=1; searchNearX=screenSizeX/2; searchNearY=screenSizeY/2; while(!stop_draw_thread) { DosGetDateTime ( &DateTime ); srand ( DateTime.hundredths * 320 ); if (trid ) { turn2D(&xAxis1Mx,&xAxis1Mz,sinA,cosA); turn2D(&xAxis2Mx,&xAxis2Mz,sinA,cosA); turn2D(&zAxis1Mx,&zAxis1Mz,sinA,cosA); turn2D(&zAxis2Mx,&zAxis2Mz,sinA,cosA); turn2D(&yAr1x,&yAr1z,sinA,cosA); turn2D(&yAr2x,&yAr2z,sinA,cosA); turn2D(&xAr1x,&xAr1z,sinA,cosA); turn2D(&xAr2x,&xAr2z,sinA,cosA); turn2D(&zAr1x,&zAr1z,sinA,cosA); turn2D(&zAr2x,&zAr2z,sinA,cosA); } if (!first) { memcpy(whitesegs_o,whitesegs,sizeof ( POINTL ) * whitecount * 4); memcpy(redsegs_o,redsegs,sizeof ( POINTL ) * redcount * 4); memcpy(bluesegs_o,bluesegs,sizeof ( POINTL ) * bluecount * 4); memcpy(yellowsegs_o,yellowsegs,sizeof ( POINTL ) * yellowcount * 4); whitecount_o= whitecount; redcount_o= redcount; bluecount_o= bluecount; yellowcount_o=yellowcount; if (isGrid) { gridX_o=gridX; gridY_o=gridY; strcpy(starName_o,starName); } } /* <=- Stars -=> */ whitecount=0; redcount=0; bluecount=0; yellowcount=0; wc=0; rc=0; bc=0; yc=0; middleX=0; middleY=0; middleZ=0; for (b = 0; b < starcount; b++) { if (trid ) { turn2D(&realX[b],&realZ[b],sinA,cosA); } middleX+=realX[b]; middleY+=realY[b]; middleZ+=realZ[b]; } middleX=middleX/starcount; middleY=middleY/starcount; middleZ=middleZ/starcount; for (b = 0; b < starcount; b++) { realX[b]-=middleX; if (!trid) realY[b]-=middleY; realZ[b]-=middleZ; } isGrid=0; minds=1e9; for (b = 0; b < starcount; b++) { for (b2=b+1 ;b2<starcount ;b2++) { if (trid) { dfx=realX[b]-realX[b2]; dfy=realY[b]-realY[b2]; dfz=realZ[b]-realZ[b2]; dd=gravity*size[b2]/((dfx*dfx)+(dfy*dfy)+(dfz*dfz)); dfx=dfx*dd; dfy=dfy*dd; dfz=dfz*dd; sx[b]=sx[b]-dfx; sy[b]=sy[b]-dfy; sz[b]=sz[b]-dfz; sx[b2]=sx[b2]+dfx; sy[b2]=sy[b2]+dfy; sz[b2]=sz[b2]+dfz; } else { dfx=realX[b]-realX[b2]; dfy=realY[b]-realY[b2]; dd=gravity*size[b2]/((dfx*dfx)+(dfy*dfy)); dfx=dfx*dd; dfy=dfy*dd; sx[b]=sx[b]-dfx; sy[b]=sy[b]-dfy; sx[b2]=sx[b2]+dfx; sy[b2]=sy[b2]+dfy; } } realX[b]=realX[b]+sx[b]; realY[b]=realY[b]+sy[b]; realZ[b]=realZ[b]+sz[b]; convertTo2D(realX[b],realY[b],realZ[b],&x[b],&y[b]); inside=isInside(x[b],y[b]); if ( wc<whiteStars ) { wc++; if (inside) { index = whitecount*4; whitesegs[index].x = x[b]; whitesegs[index].y = y[b]; whitesegs[index+1].x = x[b]+2; whitesegs[index+1].y = y[b]; whitesegs[index+2].x = x[b]; whitesegs[index+2].y = y[b]+1; whitesegs[index+3].x = x[b]+2; whitesegs[index+3].y = y[b]+1; whitecount++; } } else { if (rc<redStars ) { rc++; if (inside) { index = redcount*4; redsegs[index].x = x[b]; redsegs[index].y = y[b]; redsegs[index+1].x = x[b]+2; redsegs[index+1].y = y[b]; redsegs[index+2].x = x[b]; redsegs[index+2].y = y[b]+1; redsegs[index+3].x = x[b]+2; redsegs[index+3].y = y[b]+1; redcount++; } } else { if (bc<blueStars ) { bc++; if (inside) { index = bluecount*4; bluesegs[index].x = x[b]; bluesegs[index].y = y[b]; bluesegs[index+1].x = x[b]+2; bluesegs[index+1].y = y[b]; bluesegs[index+2].x = x[b]; bluesegs[index+2].y = y[b]+1; bluesegs[index+3].x = x[b]+2; bluesegs[index+3].y = y[b]+1; bluecount++; } } else { yc++; if (inside) { index = yellowcount*4; yellowsegs[index].x = x[b]; yellowsegs[index].y = y[b]; yellowsegs[index+1].x = x[b]+2; yellowsegs[index+1].y = y[b]; yellowsegs[index+2].x = x[b]; yellowsegs[index+2].y = y[b]+1; yellowsegs[index+3].x = x[b]+2; yellowsegs[index+3].y = y[b]+1; yellowcount++; } } } } if (inside) { isGrid=1; dsx=(searchNearX-x[b]); dsy=(searchNearY-y[b]); ds=dsx*dsx+dsy*dsy; if (ds<minds) { minds=ds; gridX=x[b]; gridY=y[b]; strcpy(starName,starNames[b % CNT_STARS]); } } } if (!first) { drawGrid(hps,gridX_o,gridY_o,0,starName_o,tracename); if ( trid ) { drawAxis(hps,yAxis12Dx,yAxis12Dy,yAxis22Dx,yAxis22Dy,xAxis12Dx,xAxis12Dy,xAxis22Dx,xAxis22Dy,zAxis12Dx,zAxis12Dy,zAxis22Dx,zAxis22Dy,0); drawArrows(hps,yAxis22Dx,yAxis22Dy,yAr12Dx,yAr12Dy,yAr22Dx,yAr22Dy,0); drawArrows(hps,xAxis22Dx,xAxis22Dy,xAr12Dx,xAr12Dy,xAr22Dx,xAr22Dy,0); drawArrows(hps,zAxis22Dx,zAxis22Dy,zAr12Dx,zAr12Dy,zAr22Dx,zAr22Dy,0); } } if (!first) { Color=CLR_BLACK; GpiSetColor ( hps , Color ); GpiPolyLineDisjoint ( hps ,whitecount_o * 4 , whitesegs_o ); } Color=CLR_WHITE; GpiSetColor ( hps , Color ); GpiPolyLineDisjoint ( hps ,whitecount * 4 , whitesegs ); if (!first) { Color=CLR_BLACK; GpiSetColor ( hps , Color ); GpiPolyLineDisjoint ( hps ,redcount_o * 4 , redsegs_o ); } Color=CLR_RED; GpiSetColor ( hps , Color ); GpiPolyLineDisjoint ( hps ,redcount * 4 , redsegs ); if (!first) { Color=CLR_BLACK; GpiSetColor ( hps , Color ); GpiPolyLineDisjoint ( hps ,bluecount_o * 4 , bluesegs_o ); } Color=CLR_BLUE; GpiSetColor ( hps , Color ); GpiPolyLineDisjoint ( hps ,bluecount * 4 , bluesegs ); if (!first) { Color=CLR_BLACK; GpiSetColor ( hps , Color ); GpiPolyLineDisjoint ( hps ,yellowcount_o * 4 , yellowsegs_o ); } Color=CLR_YELLOW; GpiSetColor ( hps , Color ); GpiPolyLineDisjoint ( hps ,yellowcount * 4 , yellowsegs ); if (isGrid) { drawGrid(hps,gridX,gridY,1,starName,tracename); searchNearX=gridX+(rand()%(4))-2; searchNearY=gridY+(rand()%(4))-2; } else { for (b = 0; b < starcount; b++) { if (trid) { realX[b] = (rand()%(4000))-2000; realY[b] = (rand()%(2000))-1000; realZ[b] = (rand()%(4000))-2000; } else { realX[b] = (rand()%(4000))-2000; realY[b] = (rand()%(4000))-2000; realZ[b] = 0; } } } if ( trid ) { convertTo2D(xAxis1Mx,xAxis1My,xAxis1Mz,&xAxis12Dx,&xAxis12Dy); convertTo2D(xAxis2Mx,xAxis2My,xAxis2Mz,&xAxis22Dx,&xAxis22Dy); convertTo2D(zAxis1Mx,zAxis1My,zAxis1Mz,&zAxis12Dx,&zAxis12Dy); convertTo2D(zAxis2Mx,zAxis2My,zAxis2Mz,&zAxis22Dx,&zAxis22Dy); convertTo2D(yAr1x,yAr1y,yAr1z,&yAr12Dx,&yAr12Dy); convertTo2D(yAr2x,yAr2y,yAr2z,&yAr22Dx,&yAr22Dy); convertTo2D(xAr1x,xAr1y,xAr1z,&xAr12Dx,&xAr12Dy); convertTo2D(xAr2x,xAr2y,xAr2z,&xAr22Dx,&xAr22Dy); convertTo2D(zAr1x,zAr1y,zAr1z,&zAr12Dx,&zAr12Dy); convertTo2D(zAr2x,zAr2y,zAr2z,&zAr22Dx,&zAr22Dy); drawAxis(hps,yAxis12Dx,yAxis12Dy,yAxis22Dx,yAxis22Dy,xAxis12Dx,xAxis12Dy,xAxis22Dx,xAxis22Dy,zAxis12Dx,zAxis12Dy,zAxis22Dx,zAxis22Dy,1); drawArrows(hps,yAxis22Dx,yAxis22Dy,yAr12Dx,yAr12Dy,yAr22Dx,yAr22Dy,1); drawArrows(hps,xAxis22Dx,xAxis22Dy,xAr12Dx,xAr12Dy,xAr22Dx,xAr22Dy,1); drawArrows(hps,zAxis22Dx,zAxis22Dy,zAr12Dx,zAr12Dy,zAr22Dx,zAr22Dy,1); } first=0; /* sleep a while if necessary */ if(low_priority == TRUE) DosSleep(10); else DosSleep(2); } /* free ( whitesegs ); free ( redsegs ); */ WinDestroyMsgQueue(drawingthread_hmq); WinTerminate(drawingthread_hab); _endthread(); }
/* draw_thread This is the drawing-thread. You have a valid presentation space handle (hps), a valid window handle (hwndSaver) and the configuration_data structure is loaded. The screen size is stored in "screenSizeX" and "screenSizeY". IMPORTANT NOTE 1: You must check the "stop_draw_thread" flag regularly. If it is set, free all resources you have allocated and call _endthread (or just return) to end the drawing-thread. IMPORTANT NOTE 2: If the "low_priority" flag is NOT set (that means you run with regular priority, sharing CPU usage with other programs), you should call DosSleep(x) with "x" set at least to 1 as often as possible, to allow other programs to do their work. A screen saver should not eat up other program's CPU time! IMPORTANT NOTE 3: For some of the PM calls to work properly, your thread needs an own HAB and maybe even a message queue. You have to get and release both of them here if you use such PM calls. The following sample code is from the "Pyramids" module that comes with the ScreenSaver distribution. It selects a random color and a random point on the screen, then draws lines in the selected color from each corner of the screen to the selected point (looks somewhat like a pyramid). It remembers a number of points (this number can be set in the configuration dialog). Having filled the point memory, it redraws the "oldest" visible pyramid in black. This has the effect that more and more pixels on the screen get black, only a few constantly changing colored lines remain. */ void draw_thread(void *args) { int i, j; const RECTL ScreenRect = { 0, 0, screenSizeX, screenSizeY }; int color_count = 0; ULONG color; int pushleftx = 11, pushlefty = 11, pushrightx = 11, pushrighty = 11; BOOL point_buffer_filled; BOOL first_paint = TRUE; POINTL *ptleft, *ptright; EXCEPTIONREGISTRATIONRECORD xcpthand = { (PEXCEPTIONREGISTRATIONRECORD)0, GPFHandler }; DosSetExceptionHandler(&xcpthand) ; i = 0; point_buffer_filled = FALSE; /* allocate memory for circular point buffer */ ptleft = malloc(configuration_data.count * sizeof(POINTL)); ptright = malloc(configuration_data.count * sizeof(POINTL)); if( (ptleft == NULL) || (ptright == NULL) ) goto end; GpiSetLineWidth( hps, LINEWIDTH_THICK ); srand(WinGetCurrentTime(hab)); do{ color = ((unsigned)rand()) % 17 - 2; }while ( color == -1 || color == 0 || color == 7 || color == 8 ); /* blank screen if requested */ if( configuration_data.blank_screen ) WinFillRect( hps, &ScreenRect, CLR_BLACK ); while(!stop_draw_thread){ if(point_buffer_filled){ /* redraw old line in black */ GpiSetColor(hps, CLR_BLACK); GpiMove(hps, &ptleft[i]); GpiLine(hps, &ptright[i]); } if( color_count == configuration_data.colors ){ /* select random color */ do{ color = ((unsigned)rand()) % 17 - 2; }while ( color == -1 || color == 0 || color == 7 || color == 8 ); color_count = 0; } GpiSetColor(hps, color); color_count++; if (first_paint ){ /* set the start coordinates */ ptleft[0].x = rand() % screenSizeX; ptleft[0].y = rand() % screenSizeY; ptright[0].x = rand() % screenSizeX; ptright[0].y = rand() % screenSizeY; first_paint = FALSE; } else { /* calculate new line points */ j = i==0 ? configuration_data.count - 1 : i - 1; ptleft[i].x = ptleft[j].x + pushleftx; ptleft[i].y = ptleft[j].y + pushlefty; ptright[i].x = ptright[j].x + pushrightx; ptright[i].y = ptright[j].y + pushrighty; } /* adjust lines if they hit a screen border */ if( ptleft[i].x >= screenSizeX ) { ptleft[i].x = 2 * screenSizeX - ptleft[i].x; pushleftx = - pushleftx + (rand() % 2); } if( ptleft[i].y >= screenSizeY ) { ptleft[i].y = 2 * screenSizeY - ptleft[i].y; pushlefty = - pushlefty + (rand() % 2); } if( ptright[i].x >= screenSizeX ) { ptright[i].x = 2 * screenSizeX - ptright[i].x; pushrightx = - pushrightx + ( rand() % 2); } if( ptright[i].y >= screenSizeY ) { ptright[i].y = 2 * screenSizeY - ptright[i].y; pushrighty = - pushrighty + ( rand() % 2); } if( ptleft[i].x < 0 ) { ptleft[i].x *= -1; pushleftx = - pushleftx + (rand() % 2); } if( ptleft[i].y < 0 ) { ptleft[i].y *= -1; pushlefty = - pushlefty + (rand() % 2); } if( ptright[i].x < 0 ) { ptright[i].x *= -1; pushrightx = - pushrightx + (rand() % 2); } if( ptright[i].y < 0 ) { ptright[i].y *= -1; pushrighty = - pushrighty + (rand() % 2); } /* draw line */ GpiMove(hps, &ptleft[i]); GpiLine(hps, &ptright[i]); /* sleep if necessary */ if(low_priority == FALSE) DosSleep(1); // sleep if user requests slower animation switch(configuration_data.animation_speed){ case 4: break; case 3: DosSleep(10); break; case 2: DosSleep(30); break; case 1: DosSleep(50); break; case 0: DosSleep(70); break; } i++; /* move circular buffer index */ if(i == configuration_data.count){ point_buffer_filled = TRUE; i = 0; } } /* free resources */ end: // goto from memory allocation free( ptleft ); free( ptright ); DosUnsetExceptionHandler(&xcpthand); _endthread(); }
// Message определяет пришедшее сообщение. VOID Clipper_ClipperMessageProcessing( PQMSG Message ) { // Устанавливаем приоритет потока. if( Message->msg == SM_PRIORITY ) { // Устанавливаем приоритет. LONG Class = (LONG) Message->mp1; LONG Delta = (LONG) Message->mp2; DosSetPriority( PRTYS_THREAD, Class, Delta, 0 ); // Запоминаем приоритет. Enhancer.Modules.Clipper->Priority = MAKELONG( Class, Delta ); } // Включаем выделение в текстовом окне. if( Message->msg == SM_BEGIN_VIO_MARKING || Message->msg == SM_END_VIO_MARKING ) { // Узнаем окно рамки. HWND Frame_window = (HWND) Message->mp1; // Если окна нет - возврат. if( !WinIsWindow( WinQueryAnchorBlock( Frame_window ), Frame_window ) ) return; // Включаем и выключаем выделение. if( Message->msg == SM_BEGIN_VIO_MARKING ) Clipper_BeginVIOMarking( Frame_window ); if( Message->msg == SM_END_VIO_MARKING ) Clipper_EndVIOMarkingAndCopyText( Frame_window ); } // Запоминаем выделенный текст. if( Message->msg == SM_COPY_VIO_TEXT ) { // Если в текстовых окнах не надо запоминать текст - возврат. if( !Clipper.Settings.Mouse_in_VIO ) return; // Узнаем окно рамки. HWND Frame_window = (HWND) Message->mp1; // Если окна нет - возврат. if( !WinIsWindow( WinQueryAnchorBlock( Frame_window ), Frame_window ) ) return; // Если выделение текста еще не начато - начинаем его. if( !Clipper_VIOMarkingIsInProcess( Frame_window ) ) Clipper_BeginVIOMarking( Frame_window ); // Иначе - завершаем выделение и запоминаем текст. else Clipper_EndVIOMarkingAndCopyText( Frame_window ); } // Вставляем текст в окно. if( Message->msg == SM_PASTE_VIO_TEXT ) { // Если в текстовых окнах не надо запоминать текст - возврат. if( !Clipper.Settings.Mouse_in_VIO ) return; // Узнаем окно рамки. HWND Frame_window = (HWND) Message->mp1; // Если окна нет - возврат. if( !WinIsWindow( WinQueryAnchorBlock( Frame_window ), Frame_window ) ) return; // Если в окне не идет выделение текста - вставляем текст. if( !Clipper_VIOMarkingIsInProcess( Frame_window ) ) Clipper_PasteTextToVIOWindow( Frame_window ); } // Запоминаем текст при нажатии средней кнопки мыши. if( Message->msg == SM_MB_CLICK ) { // Узнаем окно, с которым работает пользователь. HWND Input_window = (HWND) Message->mp1; // Если окна нет - возврат. if( !WinIsWindow( WinQueryAnchorBlock( Input_window ), Input_window ) ) return; // Узнаем окно рабочего стола. HWND Desktop = QueryDesktopWindow(); // Узнаем время, достаточное для двойного нажатия на кнопку мыши. LONG DblClk_delta = WinQuerySysValue( Desktop, SV_DBLCLKTIME ); // Выполняем задержку, чтобы избежать двойного нажатия. while( 1 ) { // Если время последнего нажатия на среднюю кнопку мыши неизвестно - произошло двойное нажатие, возврат. // В это время в очереди потока уже лежит следующее сообщение - SM_MB_DOUBLECLICK. if( WMMBDownTime() == 0 ) { // Освобождаем указатель мыши. ResetPointer(); // Возврат. return; } // Узнаем текущее время. LONG Current_time = WinGetCurrentTime( Enhancer.Application ); // Если прошло достаточно много времени - все в порядке. if( Current_time > WMMBDownTime() ) if( Current_time - WMMBDownTime() > DblClk_delta ) break; // Если время прошло через ноль - возврат. if( Current_time < WMMBDownTime() ) { // Освобождаем указатель мыши. ResetPointer(); // Возврат. return; } // Через некоторое время - устанавливаем указатель мыши "прозрачная стрелка". if( Current_time - WMMBDownTime() > ( DblClk_delta / 2 ) ) if( Resources.Pointer_for_CopyPaste != NULLHANDLE ) WinSetPointer( QueryDesktopWindow(), Resources.Pointer_for_CopyPaste ); // Выполняем задержку. Retard(); } // Освобождаем указатель мыши. ResetPointer(); // Время последнего нажатия на среднюю кнопку мыши - неизвестно. DiscardWMMBDownTime(); // Узнаем ускоритель для этого окна. LONG Accelerator = (LONG) Message->mp2; // Запоминаем текст в окне. ClipboardMouseAction( Input_window, MOUSE_CLIPBOARD_COPY, Accelerator ); } // Вставляем текст в окно при нажатии средней кнопки мыши. if( Message->msg == SM_MB_DOUBLECLICK ) { // Узнаем окно, с которым работает пользователь. HWND Input_window = (HWND) Message->mp1; // Если окна нет - возврат. if( !WinIsWindow( WinQueryAnchorBlock( Input_window ), Input_window ) ) return; // Если кнопка мыши снова была нажата - возврат. if( WMMBDownTime() ) return; // Узнаем ускоритель для этого окна. LONG Accelerator = (LONG) Message->mp2; // Вставляем текст в окно. ClipboardMouseAction( Input_window, MOUSE_CLIPBOARD_PASTE, Accelerator ); } // Вставляем текст в окно Mozilla при нажатии FireFox-клавиши. if( Message->msg >= SM_FFX_PASTE_FIRST && Message->msg <= SM_FFX_PASTE_LAST ) { // Узнаем окно, с которым работает пользователь. HWND Input_window = (HWND) Message->mp1; // Если окна нет - возврат. if( !WinIsWindow( WinQueryAnchorBlock( Input_window ), Input_window ) ) return; // Вставляем текст в окно. Clipper_PasteFireFoxCharacters( Input_window, Message->msg ); } // Восстанавливаем содержимое Clipboard. if( Message->msg == SM_RESTORE_CLIPBOARD ) Clipper_RestoreClipboard(); // Возврат. return; }
/* draw_thread This is the drawing-thread. You have a valid presentation space handle (hps), a valid window handle (hwndSaver) and the configuration_data structure is loaded. The screen size is stored in "screenSizeX" and "screenSizeY". IMPORTANT NOTE 1: You must check the "stop_draw_thread" flag regularly. If it is set, free all resources you have allocated and call _endthread (or just return) to end the drawing-thread. IMPORTANT NOTE 2: If the "low_priority" flag is NOT set (that means you run with regular priority, sharing CPU usage with other programs), you should call DosSleep(x) with "x" set at least to 1 as often as possible, to allow other programs to do their work. A screen saver should not eat up other program's CPU time! IMPORTANT NOTE 3: For some of the PM calls to work properly, your thread needs an own HAB and maybe even a message queue. You have to get and release both of them here if you use such PM calls. The following sample code is from the "Pyramids" module that comes with the ScreenSaver distribution. It selects a random color and a random point on the screen, then draws lines in the selected color from each corner of the screen to the selected point (looks somewhat like a pyramid). It remembers a number of points (this number can be set in the configuration dialog). Having filled the point memory, it redraws the "oldest" visible pyramid in black. This has the effect that more and more pixels on the screen get black, only a few constantly changing colored lines remain. */ void draw_thread(void *args) { INT i, j; typedef struct { INT x; INT y; float dx; float dy; INT step; } STAR; STAR *star; RECTL rect; BOOL point_buffer_filled; BOOL free_star_field = TRUE; float norm; EXCEPTIONREGISTRATIONRECORD xcpthand = { (PEXCEPTIONREGISTRATIONRECORD)0, GPFHandler }; DosSetExceptionHandler(&xcpthand) ; /* random seed (needed for each thread) */ srand(WinGetCurrentTime(hab)); i = 0; point_buffer_filled = FALSE; /* allocate stack memory for circular point buffer */ star = malloc(configuration_data.count * sizeof(STAR)); if( star == NULL ) stop_draw_thread = TRUE; /* blank Screen */ rect.xLeft = 0; rect.xRight = screenSizeX; rect.yBottom = 0; rect.yTop = screenSizeY; WinFillRect( hps, &rect, CLR_BLACK ); while(!stop_draw_thread){ if( free_star_field ){ /* create a new star */ star[i].x = rand() % screenSizeX/10 + screenSizeX * 9 / 20; star[i].y = rand() % screenSizeY / 10 + screenSizeY * 9 / 20; /* distance from screen center: */ star[i].dx = star[i].x - screenSizeX / 2; star[i].dy = star[i].y - screenSizeY / 2; /* it was created right in the middle: move it a little */ if( !star[i].dx && !star[i].dy) star[i].dx = 1; /* half the distance to the center: */ norm = sqrt( star[i].dx * star[i].dx + star[i].dy * star[i].dy ) / 2; if( norm < 1 ) norm = 1; /* Offsets normieren */ star[i].dx /= norm; star[i].dy /= norm; /* step counter for increasing star size: */ star[i].step = 1; rect.xLeft = star[i].x; rect.xRight = star[i].x + star[i].step / 22 + 1; rect.yBottom = star[i].y; rect.yTop = star[i].y + star[i].step / 22 + 1; WinFillRect( hps, &rect, CLR_WHITE ); } for( j = 0; j < (point_buffer_filled ? configuration_data.count : i + 1); j++){ /* move all stars */ rect.xLeft = star[j].x; rect.xRight = star[j].x + star[j].step / 22 + 1; rect.yBottom = star[j].y; rect.yTop = star[j].y + star[j].step / 22 + 1; WinFillRect( hps, &rect, CLR_BLACK ); star[j].step++; star[j].x += star[j].dx * star[j].step / 4; /* neu */ star[j].y += star[j].dy * star[j].step / 4; rect.xLeft = star[j].x; rect.xRight = star[j].x + star[j].step / 22 + 1; rect.yBottom = star[j].y; rect.yTop = star[j].y + star[j].step / 22 + 1; WinFillRect( hps, &rect, CLR_WHITE ); } i++; if( i==configuration_data.count ){ /* index wrap */ i = 0; point_buffer_filled = TRUE; free_star_field = FALSE; } if( point_buffer_filled ){ for( j = 0; j < configuration_data.count; j++){ /* check all stars whether they are still on screen */ if( star[j].x < - 10 || star[j].x > screenSizeX || star[j].y < -10 || star[j].y > screenSizeY ) { free_star_field = TRUE; i = j; break; } else { free_star_field = FALSE; } } } /* sleep if necessary */ if(low_priority == FALSE) DosSleep(1); /* sleep if user requests slower animation */ switch(configuration_data.animation_speed){ case 4: break; case 3: DosSleep(10); break; case 2: DosSleep(30); break; case 1: DosSleep(50); break; case 0: DosSleep(70); break; } } /* free resources */ free( star ); DosUnsetExceptionHandler(&xcpthand); _endthread(); }
MRESULT EXPENTRY ClientWndProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) { static INT aiPuzzle[NUMROWS][NUMCOLS], iBlankRow, iBlankCol, cxSquare, cySquare ; CHAR szNum[10] ; HPS hps ; HWND hwndFrame ; INT iRow, iCol, iMouseRow, iMouseCol, i ; POINTL ptl ; RECTL rcl, rclInvalid, rclIntersect ; SIZEL sizl ; switch (msg) { case WM_CREATE: // Calculate square size in pixels hps = WinGetPS (hwnd) ; sizl.cx = sizl.cy = 0 ; GpiSetPS (hps, &sizl, PU_LOENGLISH) ; ptl.x = SQUARESIZE ; ptl.y = SQUARESIZE ; GpiConvert (hps, CVTC_PAGE, CVTC_DEVICE, 1L, &ptl) ; WinReleasePS (hps) ; cxSquare = ptl.x ; cySquare = ptl.y ; // Calculate client window size and position rcl.xLeft = (WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN) - NUMCOLS * cxSquare) / 2 ; rcl.yBottom = (WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN) - NUMROWS * cySquare) / 2 ; rcl.xRight = rcl.xLeft + NUMCOLS * cxSquare ; rcl.yTop = rcl.yBottom + NUMROWS * cySquare ; // Set frame window position and size hwndFrame = WinQueryWindow (hwnd, QW_PARENT) ; WinCalcFrameRect (hwndFrame, &rcl, FALSE) ; WinSetWindowPos (hwndFrame, NULLHANDLE, rcl.xLeft, rcl.yBottom, rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom, SWP_MOVE | SWP_SIZE | SWP_ACTIVATE) ; // Initialize the aiPuzzle array WinSendMsg (hwnd, WM_COMMAND, MPFROMSHORT (IDM_NORMAL), NULL) ; return 0 ; case WM_PAINT: hps = WinBeginPaint (hwnd, NULLHANDLE, &rclInvalid) ; // Draw the squares for (iRow = NUMROWS - 1 ; iRow >= 0 ; iRow--) for (iCol = 0 ; iCol < NUMCOLS ; iCol++) { rcl.xLeft = cxSquare * iCol ; rcl.yBottom = cySquare * iRow ; rcl.xRight = rcl.xLeft + cxSquare ; rcl.yTop = rcl.yBottom + cySquare ; if (!WinIntersectRect (0, &rclIntersect, &rcl, &rclInvalid)) continue ; if (iRow == iBlankRow && iCol == iBlankCol) WinFillRect (hps, &rcl, CLR_BLACK) ; else { WinDrawBorder (hps, &rcl, 5, 5, CLR_PALEGRAY, CLR_DARKGRAY, DB_STANDARD | DB_INTERIOR) ; WinDrawBorder (hps, &rcl, 2, 2, CLR_BLACK, 0L, DB_STANDARD) ; sprintf (szNum, "%d", aiPuzzle[iRow][iCol]) ; WinDrawText (hps, -1, szNum, &rcl, CLR_WHITE, CLR_DARKGRAY, DT_CENTER | DT_VCENTER) ; } } WinEndPaint (hps) ; return 0 ; case WM_BUTTON1DOWN: iMouseCol = MOUSEMSG(&msg)->x / cxSquare ; iMouseRow = MOUSEMSG(&msg)->y / cySquare ; // Check if mouse was in valid area if ( iMouseRow < 0 || iMouseCol < 0 || iMouseRow >= NUMROWS || iMouseCol >= NUMCOLS || (iMouseRow != iBlankRow && iMouseCol != iBlankCol) || (iMouseRow == iBlankRow && iMouseCol == iBlankCol)) break ; // Move a row right or left if (iMouseRow == iBlankRow) { if (iMouseCol < iBlankCol) for (iCol = iBlankCol ; iCol > iMouseCol ; iCol--) aiPuzzle[iBlankRow][iCol] = aiPuzzle[iBlankRow][iCol - 1] ; else for (iCol = iBlankCol ; iCol < iMouseCol ; iCol++) aiPuzzle[iBlankRow][iCol] = aiPuzzle[iBlankRow][iCol + 1] ; } // Move a column up or down else { if (iMouseRow < iBlankRow) for (iRow = iBlankRow ; iRow > iMouseRow ; iRow--) aiPuzzle[iRow][iBlankCol] = aiPuzzle[iRow - 1][iBlankCol] ; else for (iRow = iBlankRow ; iRow < iMouseRow ; iRow++) aiPuzzle[iRow][iBlankCol] = aiPuzzle[iRow + 1][iBlankCol] ; } // Calculate invalid rectangle rcl.xLeft = cxSquare * min (iMouseCol, iBlankCol) ; rcl.yBottom = cySquare * min (iMouseRow, iBlankRow) ; rcl.xRight = cxSquare * (max (iMouseCol, iBlankCol) + 1) ; rcl.yTop = cySquare * (max (iMouseRow, iBlankRow) + 1) ; // Set new array and blank values iBlankRow = iMouseRow ; iBlankCol = iMouseCol ; aiPuzzle[iBlankRow][iBlankCol] = 0 ; // Invalidate rectangle WinInvalidateRect (hwnd, &rcl, FALSE) ; break ; case WM_CHAR: if (!(CHARMSG(&msg)->fs & KC_VIRTUALKEY) || CHARMSG(&msg)->fs & KC_KEYUP) return 0 ; // Mimic a WM_BUTTON1DOWN message iMouseCol = iBlankCol ; iMouseRow = iBlankRow ; switch (CHARMSG(&msg)->vkey) { case VK_LEFT: iMouseCol++ ; break ; case VK_RIGHT: iMouseCol-- ; break ; case VK_UP: iMouseRow-- ; break ; case VK_DOWN: iMouseRow++ ; break ; default: return 0 ; } WinSendMsg (hwnd, WM_BUTTON1DOWN, MPFROM2SHORT (iMouseCol * cxSquare, iMouseRow * cySquare), NULL) ; return 0 ; case WM_COMMAND: switch (COMMANDMSG(&msg)->cmd) { // Initialize aiPuzzle array case IDM_NORMAL: case IDM_INVERT: for (iRow = 0 ; iRow < NUMROWS ; iRow++) for (iCol = 0 ; iCol < NUMCOLS ; iCol++) aiPuzzle[iRow][iCol] = iCol + 1 + NUMCOLS * (NUMROWS - iRow - 1) ; if (COMMANDMSG(&msg)->cmd == IDM_INVERT) { aiPuzzle[0][NUMCOLS-2] = NUMCOLS * NUMROWS - 2 ; aiPuzzle[0][NUMCOLS-3] = NUMCOLS * NUMROWS - 1 ; } aiPuzzle[iBlankRow = 0][iBlankCol = NUMCOLS - 1] = 0 ; WinInvalidateRect (hwnd, NULL, FALSE) ; return 0 ; // Randomly scramble the squares case IDM_SCRAMBLE: WinSetPointer (HWND_DESKTOP, WinQuerySysPointer ( HWND_DESKTOP, SPTR_WAIT, FALSE)) ; srand ((int) WinGetCurrentTime (0)) ; for (i = 0 ; i < SCRAMBLEREP ; i++) { WinSendMsg (hwnd, WM_BUTTON1DOWN, MPFROM2SHORT (rand() % NUMCOLS * cxSquare, iBlankRow * cySquare), NULL) ; WinUpdateWindow (hwnd) ; WinSendMsg (hwnd, WM_BUTTON1DOWN, MPFROM2SHORT (iBlankCol * cxSquare, rand() % NUMROWS * cySquare), NULL) ; WinUpdateWindow (hwnd) ; } WinSetPointer (HWND_DESKTOP, WinQuerySysPointer ( HWND_DESKTOP, SPTR_ARROW, FALSE)); return 0 ; } break ; } return WinDefWindowProc (hwnd, msg, mp1, mp2) ; }
MRESULT EXPENTRY ClientWndProc (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) { static HAB hab ; static HWND hwndMenu ; static INT iCurrentRep = IDM_10 ; static INT iStatus = STATUS_READY ; static LONG lCalcRep, lRepAmts [] = { 10, 100, 1000, 10000, 100000 } ; static ULONG ulElapsedTime ; double A ; LONG lRep ; 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) ; WinUpdateWindow (hwnd) ; WinSetPointer (HWND_DESKTOP, WinQuerySysPointer (HWND_DESKTOP, SPTR_WAIT, FALSE)) ; if (WinQuerySysValue (HWND_DESKTOP, SV_MOUSEPRESENT) == 0) WinShowPointer (HWND_DESKTOP, TRUE) ; lCalcRep = lRepAmts [iCurrentRep - IDM_10] ; ulElapsedTime = WinGetCurrentTime (hab) ; for (A = 1.0, lRep = 0 ; lRep < lCalcRep ; lRep++) A = Savage (A) ; ulElapsedTime = WinGetCurrentTime (hab) - ulElapsedTime ; if (WinQuerySysValue (HWND_DESKTOP, SV_MOUSEPRESENT) == 0) WinShowPointer (HWND_DESKTOP, FALSE) ; WinSetPointer (HWND_DESKTOP, WinQuerySysPointer (HWND_DESKTOP, SPTR_ARROW, FALSE)) ; iStatus = STATUS_DONE ; WinInvalidateRect (hwnd, NULL, FALSE) ; WinUpdateWindow (hwnd) ; WinEnableMenuItem (hwndMenu, IDM_START, TRUE) ; WinEnableMenuItem (hwndMenu, IDM_ABORT, FALSE) ; return 0 ; case IDM_ABORT: // Not much we can do here return 0 ; } break ; case WM_PAINT: PaintWindow (hwnd, iStatus, lCalcRep, ulElapsedTime) ; return 0 ; } return WinDefWindowProc (hwnd, msg, mp1, mp2) ; }
/* draw_thread This is the drawing-thread. You have a valid presentation space handle (hps), a valid window handle (hwndSaver) and the configuration_data structure is loaded. The screen size is stored in "screenSizeX" and "screenSizeY". IMPORTANT NOTE 1: You must check the "stop_draw_thread" flag regularly. If it is set, free all resources you have allocated and call _endthread (or just return) to end the drawing-thread. IMPORTANT NOTE 2: If the "low_priority" flag is NOT set (that means you run with regular priority, sharing CPU usage with other programs), you should call DosSleep(x) with "x" set at least to 1 as often as possible, to allow other programs to do their work. A screen saver should not eat up other program's CPU time! IMPORTANT NOTE 3: For some of the PM calls to work properly, your thread needs an own HAB and maybe even a message queue. You have to get and release both of them here if you use such PM calls. The following sample code is from the "Pyramids" module that comes with the ScreenSaver distribution. It selects a random color and a random point on the screen, then draws lines in the selected color from each corner of the screen to the selected point (looks somewhat like a pyramid). It remembers a number of points (this number can be set in the configuration dialog). Having filled the point memory, it redraws the "oldest" visible pyramid in black. This has the effect that more and more pixels on the screen get black, only a few constantly changing colored lines remain. */ void draw_thread(void *args) { POINTL BitmapPoints[4] = { 1, 1, screenSizeX + 2, screenSizeY + 2, -1, -1, screenSizeX, screenSizeY }; POINTL l_b = { 0, 0 }, l_t = { 0, screenSizeY - 1 }, r_b = { screenSizeX - 1, 0 }, r_t = { screenSizeX - 1, screenSizeY - 1 }; INT i, step; VOID l_left() { GpiMove( hps, &l_b ); GpiLine( hps, &l_t ); } VOID l_right() { GpiMove( hps, &r_b ); GpiLine( hps, &r_t ); } VOID l_top() { GpiMove( hps, &l_t ); GpiLine( hps, &r_t ); } VOID l_bottom() { GpiMove( hps, &l_b ); GpiLine( hps, &r_b ); } srand(WinGetCurrentTime( hab )); GpiSetColor( hps, CLR_BLACK ); l_left(); while(!stop_draw_thread){ if( configuration_data.drunken ){ step = (unsigned)rand() % 8; switch ( step ){ case 0: BitmapPoints[0].x = -1; BitmapPoints[0].y = 0; BitmapPoints[1].x = screenSizeX; BitmapPoints[1].y = screenSizeY + 1; l_bottom(); break; case 1: BitmapPoints[0].x = 0; BitmapPoints[0].y = 0; BitmapPoints[1].x = screenSizeX + 1; BitmapPoints[1].y = screenSizeY + 1; l_bottom(); l_left(); break; case 2: BitmapPoints[0].x = 0; BitmapPoints[0].y = -1; BitmapPoints[1].x = screenSizeX + 1; BitmapPoints[1].y = screenSizeY; l_left(); break; case 3: BitmapPoints[0].x = 0; BitmapPoints[0].y = -2; BitmapPoints[1].x = screenSizeX + 1; BitmapPoints[1].y = screenSizeY - 1; l_left(); l_top(); break; case 4: BitmapPoints[0].x = -1; BitmapPoints[0].y = -2; BitmapPoints[1].x = screenSizeX; BitmapPoints[1].y = screenSizeY - 1; l_top(); break; case 5: BitmapPoints[0].x = -2; BitmapPoints[0].y = -2; BitmapPoints[1].x = screenSizeX - 1; BitmapPoints[1].y = screenSizeY - 1; l_top(); l_right(); break; case 6: BitmapPoints[0].x = -2; BitmapPoints[0].y = -1; BitmapPoints[1].x = screenSizeX - 1; BitmapPoints[1].y = screenSizeY; l_right(); break; case 7: BitmapPoints[0].x = -2; BitmapPoints[0].y = 0; BitmapPoints[1].x = screenSizeX - 1; BitmapPoints[1].y = screenSizeY + 1; l_right(); l_bottom(); break; } } for( i = 1; i < 5; i++){ GpiBitBlt( hps, hps, 3, BitmapPoints, ROP_SRCCOPY, BBO_IGNORE ); if( stop_draw_thread) i = 10; } // sleep if necessary if(low_priority == FALSE) DosSleep(1); // sleep if user requests slower animation switch(configuration_data.animation_speed){ case 4: break; case 3: DosSleep(10); break; case 2: DosSleep(30); break; case 1: DosSleep(50); break; case 0: DosSleep(70); break; } } // free resources _endthread(); }