home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BUG 4
/
BUGCD1997_05.BIN
/
aplic
/
clip4win
/
clip4win.exe
/
C4W30E.HUF
/
SOURCE
/
TOOLBAR.PRG
< prev
next >
Wrap
Text File
|
1994-08-30
|
10KB
|
341 lines
////////////////////////////
//
// toolbar.prg
//
// Copyright (C) 1993 Skelton Software, Kendal Cottage, Hillam, Leeds, UK.
// All Rights Reserved.
//
// Example toolbar program.
//
////////////////////////////
#define WIN_WANT_ALL
#include "windows.ch"
#include "msg.ch"
#include "paint.ch"
#define APPNAME "ToolBar"
#define ID_TOOLBAR 1000
#define ID_BTN1 101
#define ID_BTN2 102
#define ID_BTN3 103
#define ID_BTN4 104
#define ID_BTN5 105
#define ID_CHILD 2000 // this is the window the user
// doesn't know about
#define TB_HEIGHT 30
#ifndef LIB_ONLY
function main()
local hWnd, aRect, hTBWnd
local aMsg[MSG_LENGTH]
local cDIB := ReadDIB("play.bmp")
local aButtons := { {10, 5, 40, 20, cDIB, ID_BTN1}, ; // all the
{60, 5, 40, 20, cDIB, ID_BTN2}, ; // same
{110, 5, 40, 20, cDIB, ID_BTN3}, ; // bitmap
{160, 5, 40, 20, cDIB, ID_BTN4}, ; // for simplicity
{210, 5, 40, 20, cDIB, ID_BTN5} }
// set up the main window
hWnd = WndSetup(APPNAME, "Clip-4-Win Tool Bar Demo", ;
{|hWnd, nMsg, nwParam, nlParam| ;
WndProc(hWnd, nMsg, nwParam, nlParam)},;
{WM_DESTROY, WM_COMMAND, WM_SIZE}, ;
,,,, ; // default x,y,w,h
,,, ; // default icon, cursor, background brush
WS_OVERLAPPEDWINDOW + WS_CLIPCHILDREN) // window style
/*
* This sample puts the toolbar at the top of the main window's client
* area. You could use the remaining part as normal, but this can be
* painful, as it's all too easy to cause output in the part occupied
* by the toolbar. Instead, create a child window with no borders (so
* the user doesn't know it exists) and make it fill the area not used
* by the toolbar. Of course, this means changing its size if the main
* window changes size (msg WM_SIZE). The toolbar size needs to change
* as well (just the width in this example).
*
* This same technique can be useful at other times, e.g. the child
* might be a multi-line edit control.
*
* If you had a status bar, the easiest way to handle it is to put it
* at the bottom of the main window, and reduce the child window's height
* by the height of the status bar.
*/
aRect = GetClientRect(hWnd)
hTBWnd = ToolBar(hWnd, 0, 0, aRect[3], TB_HEIGHT, aButtons, ID_TOOLBAR)
if !RegisterClass(CS_HREDRAW + CS_VREDRAW + CS_DBLCLKS, , , , , "MyChild",;
{|hW, nMsg, nw, nl| DoChild(hW, nMsg, nw, nl)}, ;
{WM_PAINT, WM_COMMAND})
MessageBox( , "Can't register class", "Error", MB_ICONSTOP)
quit // failed
endif
CreateWindow("MyChild", , WS_CHILD + WS_VISIBLE, ;
0, TB_HEIGHT, aRect[3], aRect[4] - TB_HEIGHT, hWnd, ID_CHILD)
do while GetMessage(aMsg, 0, 0, 0)
TranslateMessage(aMsg)
DispatchMessage(aMsg) // WndProc() often gets called from here
enddo
if IsWindow(hWnd)
DestroyWindow(hWnd)
endif
UnregisterClass(APPNAME, _GetInstance())
return 0
function WndProc(hWnd, nMsg, nwParam, nlParam)
local hTBWnd, hWndChild, nW, nH
do case
case nMsg == WM_COMMAND
// You could send it on to the child:
// SendDlgItemMessage(hWnd, ID_CHILD, nMsg, nwParam, nlParam)
// (try it -- this works for a parent/child as well as for a dialog).
// However, the child is the selected window, so Clipper's
// output will go there:
@ 5,1 say "Parent: WM_COMMAND id = " + ltrim(str(nwParam)) + " "
case nMsg == WM_SIZE
hTBWnd = GetDlgItem(hWnd, ID_TOOLBAR) // works for non-dialogs too
hWndChild = GetDlgItem(hWnd, ID_CHILD)
if nwParam == SIZE_RESTORED .or. nwParam == SIZE_MAXIMIZED
nW = C4W_LoWord(nlParam)
nH = C4W_HiWord(nlParam)
// put toolbar at top of main client area, then child client
if IsWindow(hTBWnd) // this should be true
MoveWindow(hTBWnd, 0, 0, nW, TB_HEIGHT, .t.)
endif
if IsWindow(hWndChild)
MoveWindow(hWndChild, 0, TB_HEIGHT, nW, nH - TB_HEIGHT, .t.)
endif
endif
case nMsg == WM_DESTROY
// leave out this, and you can't exit!!
PostQuitMessage(0)
otherwise
// 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)
endcase
return 0 // 0 means we processed the msg
function DoChild(hWnd, nMsg, nwParam, nlParam)
local aPaint[PS_LENGTH], hDC
do case
case nMsg == WM_COMMAND
@ 5,1 say "Child: WM_COMMAND id = " + ltrim(str(nwParam)) + " "
case nMsg == WM_PAINT
hDC = BeginPaint(hWnd, aPaint)
TextOut(hDC, 150, 150, "Clip-4-Win ToolBar Test")
EndPaint(hWnd, aPaint)
otherwise
return DefWindowProc(hWnd, nMsg, nwParam, nlParam)
endcase
return 0 // 0 means we processed the msg
#endif // !LIB_ONLY
//
// ToolBar() -- general-purpose function for a toolbar of bitmap buttons
//
// hWnd parent window to own the toolbar
// nX, nY, nW, nH toolbar position & size within parent
// aButtons array of buttons:
// { {x,y,w,h, cDIB | hBmp, nMenuId} , ... }
// where
// x,y,w,h position & size of button in toolbar
// cDIB device-independent bitmap
// hBmp a bitmap handle
// nMenuId the menu id to send if the button is
// pressed (and released)
// nId ID of toolbar
// hBrush optional brush for background
//
function ToolBar(hWnd, nX, nY, nW, nH, aButtons, nId, hBrush)
static lWClass := .f., aBtn
local hWin, hCurWnd := SelectWindow()
if hBrush == nil
hBrush = GetStockObject(LTGRAY_BRUSH) // typical colour for a toolbar
endif
aBtn = aButtons
if !lWClass
// register a window class to capture the mouse messages
if !(lWClass := RegisterClass(CS_HREDRAW + CS_VREDRAW, ;
, , , hBrush, "C4WTlBar", ;
{|hW, nMsg, nw, nl| ;
DoToolBar(hW, nMsg, nw, nl, aBtn, hWnd)},;
{WM_PAINT, ;
WM_LBUTTONDOWN, WM_MOUSEMOVE, ;
WM_LBUTTONUP}))
return 0 // failed
endif
endif
if (hWin := CreateWindow("C4WTlBar", , WS_CHILD + WS_VISIBLE, ;
nX, nY, nW, nH, hWnd, nId)) == 0
return 0 // failed
endif
SelectWindow(hCurWnd)
return hWin
static function DoToolBar(hWnd, nMsg, nwParam, nlParam, aButtons, hWin)
static lPressed := .f., aBtn, lDrawnDown := .f.
local nBtn
local aPaint[PS_LENGTH], hDC, aRect, hOldPen
local nX, nY
do case
case nMsg == WM_MOUSEMOVE
nX = C4W_LoWord(nlParam) // mouse pos
nY = C4W_HiWord(nlParam)
if lPressed
// may have moved on or off the button
if aBtn[1] <= nX .and. nX < aBtn[1]+aBtn[3] ;
.and. aBtn[2] <= nY .and. nY < aBtn[2]+aBtn[4]
// inside the selected button
if !lDrawnDown
// gone back inside the button, so draw it down
hDC = GetDC(hWnd)
DrawBtn(hDC, aBtn, lDrawnDown := .t.)
ReleaseDC(hWnd, hDC)
endif
else
if lDrawnDown
// gone outside the button, so draw it up
hDC = GetDC(hWnd)
DrawBtn(hDC, aBtn, lDrawnDown := .f.)
ReleaseDC(hWnd, hDC)
endif
endif
endif
case nMsg == WM_LBUTTONDOWN
nX = C4W_LoWord(nlParam) // mouse pos
nY = C4W_HiWord(nlParam)
nBtn = ascan(aButtons, ;
{|aBtn| aBtn[1] <= nX .and. nX < aBtn[1]+aBtn[3] ;
.and. aBtn[2] <= nY .and. nY < aBtn[2]+aBtn[4]})
if lPressed := (nBtn != 0)
hDC = GetDC(hWnd)
DrawBtn(hDC, aBtn := aButtons[nBtn], lDrawnDown := .t.)
ReleaseDC(hWnd, hDC)
SetCapture(hWnd) // steal all mouse messages
endif
case nMsg == WM_LBUTTONUP
ReleaseCapture() // finished stealing mouse messages
nX = C4W_LoWord(nlParam) // mouse pos
nY = C4W_HiWord(nlParam)
if lDrawnDown
hDC = GetDC(hWnd)
DrawBtn(hDC, aBtn, .f.)
ReleaseDC(hWnd, hDC)
endif
// only button up when inside a pressed button sends a message
if lPressed ;
.and. aBtn[1] <= nX .and. nX < aBtn[1]+aBtn[3] ;
.and. aBtn[2] <= nY .and. nY < aBtn[2]+aBtn[4]
PostMessage(hWin, WM_COMMAND, aBtn[6], 0)
endif
lPressed := lDrawnDown := .f.
case nMsg == WM_PAINT
hDC = BeginPaint(hWnd, aPaint)
aeval(aButtons, {|aBtn| DrawBtn(hDC, aBtn, .f.)})
// draw a border (if you want 3-D see DrawBtn() for ideas)
aRect = GetClientRect(hWnd)
hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN))
MoveTo(hDC, 0, 0)
LineTo(hDC, nX := aRect[3] - 1, 0) // -1 to be inside aRect
LineTo(hDC, nX, nY := aRect[4] - 1)
LineTo(hDC, 0, nY)
LineTo(hDC, 0, 0)
SelectObject(hDC, hOldPen)
EndPaint(hWnd, aPaint)
otherwise
return DefWindowProc(hWnd, nMsg, nwParam, nlParam)
endcase
return 0 // 0 means we processed the msg
static procedure DrawBtn(hDC, aBtn, lPressed)
local nDX, nDY
local nLeft, nTop, nRight, nBottom
local hMemDC, hOldBmp
local hOldPen
nLeft = aBtn[1]
nTop = aBtn[2]
nRight = nLeft + aBtn[3]
nBottom = nTop + aBtn[4]
if lPressed
nDX := nDY := 2 // shift across and down
else
nDX := nDY := 0
endif
if valtype(aBtn[5]) == "N"
// a bitmap handle
hMemDC := CreateCompatibleDC(hDC)
hOldBmp := SelectObject(hMemDC, aBtn[5])
BitBlt(hDC, nLeft + nDX, nTop + nDY, aBtn[3], aBtn[4], ;
hMemDC, 0, 0)
SelectObject(hMemDC, hOldBmp)
DeleteDC(hMemDC)
else
ShowDIB(hDC, aBtn[5], nLeft + nDX, nTop + nDY)
endif
hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN))
// draw border
MoveTo(hDC, nLeft, nBottom)
LineTo(hDC, nLeft, nTop)
LineTo(hDC, nRight, nTop)
LineTo(hDC, nRight, nBottom)
LineTo(hDC, nLeft, nBottom)
// draw 3-d effect
SelectObject(hDC, GetStockObject(iif(lPressed, BLACK_PEN, WHITE_PEN)))
nLeft++ ; nRight-- ; nTop++ ; nBottom--
MoveTo(hDC, nLeft, nBottom)
LineTo(hDC, nLeft, nTop)
LineTo(hDC, nRight, nTop)
SelectObject(hDC, GetStockObject(iif(lPressed, WHITE_PEN, BLACK_PEN)))
LineTo(hDC, nRight, nBottom)
LineTo(hDC, nLeft, nBottom)
SelectObject(hDC, hOldPen)
return
static function CreateCompatibleDC(hDC)
local hLib := LoadLibrary("GDI.EXE")
local c := GetProcAddress(hLib, "CreateCompatibleDC", "Pascal", ;
"int", "int")
return CallDLL(c, hDC)