home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BUG 4
/
BUGCD1997_05.BIN
/
aplic
/
clip4win
/
clip4win.exe
/
C4W30E.HUF
/
SOURCE
/
ODRAW.PRG
< prev
next >
Wrap
Text File
|
1993-10-19
|
11KB
|
413 lines
////////////////////////////
//
// odraw.prg
//
// Copyright (C) 1993 Skelton Software, Kendal Cottage, Hillam, Leeds, UK.
// All Rights Reserved.
//
// Owner Draw examples.
//
////////////////////////////
#define WIN_WANT_ALL
#include "windows.ch"
#include "msg.ch"
#include "paint.ch"
#include "drawitem.ch"
// You can define this to get TAB, arrows, etc. between controls,
// like in a dialog. Don't define it if you don't want these keystrokes
// used that way!
#define LIKE_DIALOG
#define APPNAME "ODRAW"
#ifdef LIKE_DIALOG
#define BUTTONSTYLE WS_CHILD + WS_VISIBLE + BS_OWNERDRAW + WS_TABSTOP
#else
#define BUTTONSTYLE WS_CHILD + WS_VISIBLE + BS_OWNERDRAW
#endif // LIKE_DIALOG
#define IDC_BTN0 10
#define IDC_BTN1 11
#define IDC_BTN2 12
#define IDC_BTN3 13
static nBtn := 0 // the button id
static nBN := 0 // notification code
function main()
local hWnd
local aMsg[MSG_LENGTH]
local hBtn0, hBtn1, hBtn2, hBtn3
// set up the main window
hWnd = WndSetup(APPNAME, "Clip-4-Win Owner Draw Demo", ;
{|hWnd, nMsg, nwParam, nlParam| ;
WndProc(hWnd, nMsg, nwParam, nlParam)},;
{WM_DESTROY, WM_COMMAND, ;
WM_PAINT, ;
WM_RBUTTONDOWN, ;
WM_DRAWITEM}, ; // sent when time to draw the owner-draw item
,,,, ; // default x,y,w,h
,,, ; // default icon, cursor, background brush
WS_OVERLAPPEDWINDOW + WS_CLIPCHILDREN) // window style
// a pre-packaged owner-drawn button (PRG source for BitmapButton() is below)
hBtn0 = BitmapButton(hWnd, ; // parent
300, 150, ; // x,y
40, 20, ; // width, height
ReadDIB("play.bmp"),; // bitmap to show
{|| SetPos(1,1), qout("single click")},;
{|| SetPos(1,1), qout("double click")},;
IDC_BTN0) // id to use
// let's have some owner-drawn buttons
hBtn1 = CreateWindow("button", ; // wind class
"", ; // text
BUTTONSTYLE, ; // style
250, 200, ; // x,y
40, 20, ; // w,h
hWnd, ; // parent
IDC_BTN1) // the id's are what tell these apart
// (hBtn1, hBtn2 etc. would do, too)
hBtn2 = CreateWindow("button", ;
"", ;
BUTTONSTYLE, ;
350, 200, ;
40, 20, ;
hWnd, ;
IDC_BTN2)
hBtn3 = CreateWindow("button", ;
"", ;
BUTTONSTYLE, ;
280, 250, ;
80, 40, ;
hWnd, ;
IDC_BTN3)
#ifdef LIKE_DIALOG
SetFocus(hBtn0)
do while GetMessage(aMsg, 0, 0, 0)
if IsWindow(hWnd) .and. !IsDialogMessage(hWnd, aMsg)
TranslateMessage(aMsg)
DispatchMessage(aMsg) // WndProc() often gets called from here
endif
enddo
#else
do while GetMessage(aMsg, 0, 0, 0)
TranslateMessage(aMsg)
DispatchMessage(aMsg) // WndProc() often gets called from here
enddo
#endif // LIKE_DIALOG
if IsWindow(hWnd)
DestroyWindow(hWnd)
endif
UnregisterClass(APPNAME, _GetInstance())
return aMsg[MSG_wParam]
function WndProc(hWnd, nMsg, nwParam, nlParam)
local aPaint[PS_LENGTH], hDC
do case
case nMsg == WM_PAINT
hDC = BeginPaint(hWnd, aPaint)
TextOut(hDC, 50, 100, "Id" + str(nBtn))
TextOut(hDC, 50, 120, "Notification code" + str(nBN))
EndPaint(hWnd, aPaint)
return 0 // 0 means we processed the msg
case nMsg == WM_DRAWITEM
// decode what/why/who from
// (using the id, but you could test
// C4W_LoWord(nlParam) == hBtn1, etc.)
do case
case nwParam == IDC_BTN1
return DrawBtn1(hWnd, nMsg, nwParam, nlParam)
case nwParam == IDC_BTN2
return DrawBtn2(hWnd, nMsg, nwParam, nlParam)
case nwParam == IDC_BTN3
return DrawBtn3(hWnd, nMsg, nwParam, nlParam)
endcase
case nMsg == WM_COMMAND
do case
case nwParam == IDC_BTN1 ;
.or. nwParam == IDC_BTN2 ;
.or. nwParam == IDC_BTN3
nBtn = nwParam // save the id
nBN = C4W_HiWord(nlParam) // save the notification code
InvalidateRect(hWnd)
// This doesn't appear to be needed...
//#ifdef LIKE_DIALOG
// SetFocus(C4W_LoWord(nlParam))
//#endif // LIKE_DIALOG
return 0 // 0 means we processed the msg
endcase
case nMsg == WM_DESTROY
// leave out this, and you can't exit!!
PostQuitMessage(0)
return 0 // 0 means we processed the msg
case nMsg == WM_RBUTTONDOWN
// GetDlgItem() works for a parent and child
DestroyWindow(GetDlgItem(hWnd, IDC_BTN0))
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)
#ifdef LIKE_DIALOG
#define BMPBTNSTYLE WS_CHILD + WS_VISIBLE + WS_TABSTOP
#else
#define BMPBTNSTYLE WS_CHILD + WS_VISIBLE
#endif // LIKE_DIALOG
//
// BitmapButton() -- general-purpose function for a button showing a bitmap
//
function BitmapButton(hWnd, nX, nY, nW, nH, cDIB, bClick, bDblClick, nId)
static lWClass := .f., aBtn := {}
local hWin, hBtn, hCurWnd := SelectWindow()
if !lWClass
// register a window class to capture the button messages
if !(lWClass := RegisterClass(0, , , , , "BmpButtn", ;
{|hW, nMsg, nw, nl| ;
DoBmpBtn(hW, nMsg, nw, nl, aBtn)},;
{WM_COMMAND, WM_DESTROY, ;
WM_DRAWITEM, WM_SETFOCUS}))
return 0 // failed
endif
endif
if (hWin := CreateWindow("BmpButtn", , BMPBTNSTYLE, ;
nX, nY, nW, nH, hWnd, nId)) == 0 ;
.or. (hBtn := CreateWindow("button", "", BUTTONSTYLE, ;
0, 0, nW, nH, hWin, nId)) == 0
return 0 // failed
endif
aadd(aBtn, {hWin, cDIB, bClick, bDblClick})
SelectWindow(hCurWnd)
return hBtn
static function DoBmpBtn(hWnd, nMsg, nwParam, nlParam, aBtn)
local i, nBN
local aDIS, hDC
local nDX, nDY
local nLeft, nTop, nRight, nBottom
local lSelected, hOldPen
do case
case nMsg == WM_DRAWITEM
// nlParam is LPDRAWITEMSTRUCT (i.e. a C pointer to 26 bytes of data)
aDIS := bin2a(c4w_peek(nlParam, 26), DIS_STRUCT_DEF)
hDC := aDIS[DIS_hDC]
nDX := nDY := 0
nLeft := aDIS[DIS_rcLeft]
nTop := aDIS[DIS_rcTop]
nRight := aDIS[DIS_rcRight] - 1
nBottom := aDIS[DIS_rcBottom] - 1
if (i := ascan(aBtn, {|a| a[1] == hWnd})) == 0 ;
.or. aDIS[DIS_CtlType] != ODT_BUTTON
return DefWindowProc(hWnd, nMsg, nwParam, nlParam)
endif
if lSelected := (C4W_And(aDIS[DIS_itemState], ODS_SELECTED) != 0)
nDX := nDY := 2 // shift across and down
endif
ShowDIB(hDC, aBtn[i, 2], nDX, nDY)
if C4W_And(aDIS[DIS_itemState], ODS_FOCUS) != 0
DrawFocusRect(hDC, {nLeft + 4, nTop + 4, nRight - 4, nBottom - 4})
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(lSelected, BLACK_PEN, WHITE_PEN)))
nLeft++ ; nRight-- ; nTop++ ; nBottom--
MoveTo(hDC, nLeft, nBottom)
LineTo(hDC, nLeft, nTop)
LineTo(hDC, nRight, nTop)
SelectObject(hDC, GetStockObject(iif(lSelected, WHITE_PEN, BLACK_PEN)))
LineTo(hDC, nRight, nBottom)
LineTo(hDC, nLeft, nBottom)
SelectObject(hDC, hOldPen)
return 0 // 0 means we processed the msg
case nMsg == WM_COMMAND
if (i := ascan(aBtn, {|a| a[1] == hWnd})) != 0
// found the button
if (nBN := C4W_HiWord(nlParam)) == BN_CLICKED
eval(aBtn[i, 3])
elseif nBN == BN_DOUBLECLICKED
eval(aBtn[i, 4])
endif
// This doesn't appear to be needed...
//#ifdef LIKE_DIALOG
// SetFocus(C4W_LoWord(nlParam))
//#endif // LIKE_DIALOG
return 0
endif
#ifdef LIKE_DIALOG
case nMsg == WM_SETFOCUS
// ? "SetFocus"
if (i := ascan(aBtn, {|a| a[1] == hWnd})) != 0
// ?? " to child", i
SetFocus(GetWindow(hWnd, GW_CHILD)) // focus to the button
endif
#endif // LIKE_DIALOG
case nMsg == WM_DESTROY
if (i := ascan(aBtn, {|a| a[1] == hWnd})) != 0
adel(aBtn, i) // remove it, now it's gone
asize(aBtn, len(aBtn) - 1)
endif
endcase
return DefWindowProc(hWnd, nMsg, nwParam, nlParam)
// this one's very simple, but doesn't do much
static function DrawBtn1(hWnd, nMsg, nwParam, nlParam)
static cDIB
// nMsg == WM_DRAWITEM, so nlParam is LPDRAWITEMSTRUCT (i.e. a C pointer)
local aDIS := bin2a(c4w_peek(nlParam, 26), DIS_STRUCT_DEF)
local hDC := aDIS[DIS_hDC]
if cDIB == nil
cDIB = ReadDIB("play.bmp")
endif
if aDIS[DIS_CtlType] == ODT_BUTTON
ShowDIB(hDC, cDIB)
return 0 // 0 means we processed the msg
endif
return DefWindowProc(hWnd, nMsg, nwParam, nlParam)
// this one's more interesting
static function DrawBtn2(hWnd, nMsg, nwParam, nlParam)
static cDIB
local aDIS := bin2a(c4w_peek(nlParam, 26), DIS_STRUCT_DEF)
local hDC := aDIS[DIS_hDC]
local nDX := 0, nDY := 0
local nLeft := aDIS[DIS_rcLeft], nTop := aDIS[DIS_rcTop], ;
nRight := aDIS[DIS_rcRight] - 1, nBottom := aDIS[DIS_rcBottom] - 1
local lSelected, hOldPen
if aDIS[DIS_CtlType] != ODT_BUTTON
return DefWindowProc(hWnd, nMsg, nwParam, nlParam)
endif
if cDIB == nil
cDIB = ReadDIB("play.bmp")
endif
if lSelected := (C4W_And(aDIS[DIS_itemState], ODS_SELECTED) != 0)
nDX := nDY := 2 // shift across and down
endif
ShowDIB(hDC, cDIB, nDX, nDY)
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(lSelected, BLACK_PEN, WHITE_PEN)))
nLeft++ ; nRight-- ; nTop++ ; nBottom--
MoveTo(hDC, nLeft, nBottom)
LineTo(hDC, nLeft, nTop)
LineTo(hDC, nRight, nTop)
SelectObject(hDC, GetStockObject(iif(lSelected, WHITE_PEN, BLACK_PEN)))
LineTo(hDC, nRight, nBottom)
LineTo(hDC, nLeft, nBottom)
SelectObject(hDC, hOldPen)
return 0 // 0 means we processed the msg
// this one's more interesting
static function DrawBtn3(hWnd, nMsg, nwParam, nlParam)
static cDIB
local aDIS := bin2a(c4w_peek(nlParam, 26), DIS_STRUCT_DEF)
local hDC := aDIS[DIS_hDC]
local nDX := 0, nDY := 0
local nLeft := aDIS[DIS_rcLeft], nTop := aDIS[DIS_rcTop], ;
nRight := aDIS[DIS_rcRight] - 1, nBottom := aDIS[DIS_rcBottom] - 1
local lSelected, hOldPen
if aDIS[DIS_CtlType] != ODT_BUTTON
return DefWindowProc(hWnd, nMsg, nwParam, nlParam)
endif
if cDIB == nil
cDIB = ReadDIB("play.bmp")
endif
if lSelected := (C4W_And(aDIS[DIS_itemState], ODS_SELECTED) != 0)
nDX := nDY := 2 // shift across and down
endif
StretchDIBits(hDC, ;
nDX, nDY, nRight, nBottom, ;
, , , , ;
, cDIB)
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(lSelected, BLACK_PEN, WHITE_PEN)))
nLeft++ ; nRight-- ; nTop++ ; nBottom--
MoveTo(hDC, nLeft, nBottom)
LineTo(hDC, nLeft, nTop)
LineTo(hDC, nRight, nTop)
SelectObject(hDC, GetStockObject(iif(lSelected, WHITE_PEN, BLACK_PEN)))
LineTo(hDC, nRight, nBottom)
LineTo(hDC, nLeft, nBottom)
SelectObject(hDC, hOldPen)
return 0 // 0 means we processed the msg