******************** * C4W2NTK TUTORIAL ******************** * This is a NTK emulation of the original C4W sample named: * \CLIP4WIN\SOURCE\DRAW.PRG * * * The NTK make procedure is: * MKRAD DRAW * * * I can't believe it's Clip4Win! * Powered by NTK - http://www.ntkproject.com ******************** //////////////////////////// // // draw.prg // // Copyright (C) 1993 Skelton Software, Kendal Cottage, Hillam, Leeds, UK. // All Rights Reserved. // // Drawing program, using a window procedure. // // Instructions: // press left mouse button somewhere in the client area // move around // release button // // (use system box or Alt-F4 to make program exit) // //////////////////////////// /* #define WIN_WANT_ALL #include "windows.ch" #include "msg.ch" #include "paint.ch" */ #include "windows.ch" // jnd: just add that for NTK #include "ntkmsg.ch" // Window messages def. #include "c4w2ntk.ch" // C4W msg def and NTK translations #include "ntkcmd.ch" // NTK rad msg and cmd def. (i.e. @...Say ) #include "ntkgdi.ch" #include "ntkimg.ch" #include "wNtk.ch" #define MAXPOINTS 2000 #define MOUSE_LBUTTON MK_LBUTTON // from windows.ch static aX[MAXPOINTS] static aY[MAXPOINTS] function main() local hWnd local aMsg[MSG_LENGTH] local cAppName := "Draw" //if _GetPrevInstance() == 0 if !RegisterClass(CS_HREDRAW + CS_VREDRAW, ; // class style _GetInstance(), ; // app instance LoadIcon(0, IDI_APPLICATION), ; // icon LoadCursor(0, IDC_CROSS), ; // cursor GetStockObject(WHITE_BRUSH), ; // background brush cAppName, ; // app name {|hWnd, nMsg, nwParam, nlParam| ; WndProc(hWnd, nMsg, nwParam, nlParam)}, ; // window proc {WM_DESTROY, ; WM_LBUTTONDOWN, WM_LBUTTONUP,; WM_MOUSEMOVE, ; WM_PAINT}, ; ) // defaults for the rest // (an important default is RCF_WINDOW, // so unwanted msgs go to the default handler) return -1 endif //endif hWnd = CreateWindow(cAppName, ; // window class "Join the dots", ; // caption for title bar WS_OVERLAPPEDWINDOW,; // window style CW_USEDEFAULT, ; // x co-ordinate CW_USEDEFAULT, ; // y co-ordinate CW_USEDEFAULT, ; // width CW_USEDEFAULT, ; // height 0, ; // hWnd of parent (none) 0, ; // hMenu of menu (none yet) _GetInstance()) // our own app instance if hWnd == 0 MessageBox(, "Window Creation Failed!", "Error", MB_ICONEXCLAMATION + MB_OK) return -1 endif MessageBox( , str( C4W_And(130,2) ), "C4W_And(130,2)" ) MessageBox( , str( C4W_Or(130,1) ), "C4W_Or(130,1)" ) MessageBox( , str( C4W_Or(130,2) ), "C4W_Or(130,2)" ) MessageBox( , str( C4W_Or(130,3) ), "C4W_Or(130,3)" ) MessageBox( , str( C4W_Not(0) ), "C4W_Not(0)" ) MessageBox( , str( C4W_Not(-1) ), "C4W_Not(-1)" ) // make sure it's displayed ... //ShowWindow(hWnd, _GetnCmdShow()) ShowWindow(hWnd, SW_SHOW ) // ... and up to date UpdateWindow(hWnd) // WndProc() can get called from here do while GetMessage(aMsg, 0, 0, 0) TranslateMessage(aMsg) DispatchMessage(aMsg) // WndProc() often gets called from here enddo UnregisterClass(cAppName, _GetInstance()) return aMsg[MSG_wParam] function WndProc(hWnd, nMsg, nwParam, nlParam) static nCount := 0 local aPaint[PS_LENGTH], hDC, i, j do case case nMsg == WM_LBUTTONDOWN // this is logically the 1st event we want to handle... nCount = 0 InvalidateRect(hWnd) return 0 // 0 means we processed the msg case nMsg == WM_MOUSEMOVE // ... but it would be faster to put this first // (only matters on a _slow_ cpu) ... if C4W_And(nwParam, MOUSE_LBUTTON) != 0 .and. nCount < MAXPOINTS nCount++ aX[nCount] = c4w_LoWord(nlParam) aY[nCount] = c4w_HiWord(nlParam) // leave a trail of black dots hDC = GetDC(hWnd) SetPixel(hDC, aX[nCount], aY[nCount], RGB(0,0,0)) ReleaseDC(hWnd, hDC) endif return 0 // 0 means we processed the msg case nMsg == WM_LBUTTONUP // ... then this is the last of the sequence, before... InvalidateRect(hWnd) return 0 // 0 means we processed the msg case nMsg == WM_CTLCOLOR case nMsg == WM_PAINT // ... now we join the dots in many ways! hDC = BeginPaint(hWnd, aPaint) for i = 1 to nCount - 1 for j = 1 to nCount MoveTo(hDC, aX[i], aY[i]) LineTo(hDC, aX[j], aY[j]) next j next i EndPaint(hWnd, aPaint) return 0 // 0 means we processed the msg case nMsg == WM_DESTROY // leave out this, and you can't exit!! PostQuitMessage(0) return 0 // 0 means we processed the msg endcase // This could _only_ get used with WM_USER and above msgs -- because of // the array of msgs we specified with RegisterClass() -- and we're // not using WM_USER etc. However, it's always a good idea to allow // for the unexpected. return DefWindowProc(hWnd, nMsg, nwParam, nlParam)