Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Live Controls Scroll.c
/* |
File: Scroll Controls Offscreen.c |
Contains: Sample code illustrating scrolling of controls via an off screen GWorld |
Written by: Geoff Stahl (ggs) |
Copyright: Copyright (c) 1999 Apple Computer, Inc., All Rights Reserved. |
You may incorporate this Apple sample source code into your program(s) without |
restriction. This Apple sample source code has been provided "AS IS" and the |
responsibility for its operation is yours. You are not permitted to redistribute |
this Apple sample source code as "Apple sample source code" after having made |
changes. If you're going to re-distribute the source, we require that you make |
it clear in the source that the code was descended from Apple sample source |
code, but that you've made changes. |
*/ |
// system includes ---------------------------------------------------------- |
#include <MacMemory.h> |
#include <Events.h> |
#include <Fonts.h> |
#include <Windows.h> |
#include <TextEdit.h> |
#include <Dialogs.h> |
#include <Sound.h> |
#include <SoundInput.h> |
#include <ToolUtils.h> |
#include <OSUtils.h> |
#include <Controls.h> |
#include <Devices.h> |
#include <LowMem.h> |
#include <stdlib.h> |
// project includes --------------------------------------------------------- |
// statics/globals (internal only) ------------------------------------------ |
// Menu defs |
enum |
{ |
kMenuApple = 128, |
kMenuFile = 129, |
kFileQuit = 1, |
kButtonMenuID = 150 |
}; |
enum |
{ |
// Window Constants |
kOffScreenHeight = 1600, // self e. |
kOffScreenWidth = 900, // " |
kWindowHeight = 400, // " |
kWindowWidth = 500, // " |
kWindowOffset = 100, // " |
// Scroll bar constants |
kScrollBarWidth = 16, // fixed |
kScrollArrowWidth = kScrollBarWidth, // " |
kScrollBarWidthAdjust = kScrollBarWidth - 1, // " |
kPageOverlap = 10, // overlap for a page down or up |
kThumbTrackSlop = 100, // delta from scroll bar for snap to start |
kNumControls = 400 // number of controls |
}; |
Rect gRectWindowGbl; // window rectanglein global coordinates |
ControlHandle ghControls [kNumControls]; // test controls |
Point gPtCntlPos [kNumControls]; // initial control postions |
WindowPtr gpWindow = NULL; // main window |
GWorldPtr gpGWOffScreen = NULL; // main window offscreen scratch |
short gScrollVThumbSize = 0; |
short gScrollHThumbSize = 0; |
short gTotalVSizeAdjust = 0; |
short gTotalHSizeAdjust = 0; |
ControlHandle ghHScrollBar = NULL; // main window scroll bar |
ControlHandle ghVScrollBar = NULL; // main window scroll bar |
RgnHandle gSaveClip = NULL; // clipping save for control drawing exclusions |
ControlRef gControl; // active scroll control |
SInt32 gStartValue; // scroll start value |
SInt32 gValueSlop; // slop for mouse live scroll calcs |
SInt32 gSaveValue; // current scroll value on live exit |
SInt32 gSleepTime = 60; // WaitNextEvent sleep time |
Boolean gDone = false; // done yet |
// functions Prototypes (internal/private) ----------------------------------- |
void CleanUp (void); // clean ups after application |
void ScrollControls (WindowPtr pWinParent, short left, short top); // moves postion of controls in relation to scrolled positon of window without updating |
void ScrollDrawContent (WindowPtr pWindow, short wWindowLeft, short wWindowTop); // draws contents from offscreen to on and diretcly draws scroll bar on screen |
void DoUpdate (WindowPtr pWindow); // draw from off screen to on and updates control postions on screen for events |
void MoveScroll (ControlHandle hScrollBar, short wDist); // adjust scroll bar cotnrol position accouting for control limits |
pascal void ProcScroll (ControlHandle hControl, short wPart); // proc to handle clicks in scroll bar gray or arrows (page up/down, line up/down) |
void EndThumbTracking (void); // handles release of live scroll |
SInt32 CalcValueFromPoint (ControlHandle hControl, Point thePoint); // converts mouse to scroll postion and handles out of slop area |
pascal void ProcScrollThumbAction (void); // proc to handle live scrolling |
OSErr BeginThumbTracking (ControlRef hControl); // handles beginning of live scrolling |
void DrawOneControlOffscreen (ControlHandle hControl); // updates the image of hControl for offscreen |
void DoContentClick (WindowPtr pWindow, EventRecord * pEvent); // overall content click handler |
void DoMenu (SInt32 menuResult); // menu event handler |
void DoEvent (void); // event handler |
void DrawOffScreen (CGrafPtr pCGOffScreen); // offscreen update (this would also be called for control value updates) |
void SetScrollParams (WindowPtr hWindow); // sets scroll bar size reference vars |
void AdjustScrollBar (WindowPtr pWindow, ControlHandle scrollBar); // sets appearance savvy portional scroll bar up |
void InitToolbox(void); // standard inits |
Boolean SetUp (void); // application setup |
// NOTE: Initial control position is stored in gPtCntlPos Point array to allow reference during scrolling, |
// functions (internal/private) --------------------------------------------- |
void CleanUp (void) |
{ |
MenuHandle hMenu; |
HideWindow (gpWindow); |
KillControls (gpWindow); |
if (gpWindow) |
DisposeWindow (gpWindow); |
gpWindow = NULL; |
if (gpGWOffScreen) |
DisposeGWorld (gpGWOffScreen); |
gpGWOffScreen = NULL; |
hMenu = GetMenu (kButtonMenuID); |
DeleteMenu (kButtonMenuID); |
DisposeMenu (hMenu); |
hMenu = GetMenu (kButtonMenuID); |
DeleteMenu (kMenuFile); |
DisposeMenu (hMenu); |
hMenu = GetMenu (kButtonMenuID); |
DeleteMenu (kMenuApple); |
DisposeMenu (hMenu); |
} |
// -------------------------------------------------------------------------- |
void ScrollControls (WindowPtr pWinParent, short left, short top) |
{ |
Rect rectNull = {0, 0, 0, 0}; |
GrafPtr pGrafSave; |
RgnHandle hRgnClipSave; |
short i; |
GetPort (&pGrafSave); |
SetPort ((GrafPtr) pWinParent); |
// set the clip region to empty to avoid updates |
hRgnClipSave = NewRgn (); |
GetClip ( hRgnClipSave ); |
ClipRect ( &rectNull ); |
// move controls to support mouse down events in the window |
for (i = 0; i < kNumControls; i++) |
if (((gPtCntlPos [i].v - top) != (**ghControls[i]).contrlRect.top) || ((gPtCntlPos [i].h - left) != (**ghControls[i]).contrlRect.left))// move Controls for window pos using top stored in refcon |
MoveControl (ghControls[i], gPtCntlPos [i].h - left, gPtCntlPos [i].v - top); |
SetClip (hRgnClipSave); |
SetPort (pGrafSave); |
} |
// -------------------------------------------------------------------------- |
void ScrollDrawContent (WindowPtr pWindow, short wWindowLeft, short wWindowTop) // offset and draw window content from offscreen to on |
{ |
Rect rectDest = ((GrafPtr)pWindow)->portRect; |
Rect rectSource = ((GrafPtr)pWindow)->portRect; |
GrafPtr pCGrafSave; |
GetPort (&pCGrafSave); |
SetPort ((GrafPtr) pWindow); |
OffsetRect (&rectSource, wWindowLeft, wWindowTop); // offset for position in offscreen |
rectDest.right -= kScrollBarWidthAdjust; // don't draw scroll bars |
rectDest.bottom -= kScrollBarWidthAdjust; |
rectSource.right -= kScrollBarWidthAdjust; |
rectSource.bottom -= kScrollBarWidthAdjust; |
CopyBits (&((GrafPtr)gpGWOffScreen)->portBits, &pWindow->portBits, &rectSource, &rectDest, srcCopy, NULL); |
Draw1Control (ghHScrollBar); // draw scroll bar |
Draw1Control (ghVScrollBar); // draw scroll bar |
SetPort (pCGrafSave); |
} |
// -------------------------------------------------------------------------- |
void DoUpdate (WindowPtr pWindow) |
{ |
ScrollDrawContent (pWindow, GetControlValue (ghHScrollBar), GetControlValue (ghVScrollBar)); // draw content offscreen to on |
ScrollControls (pWindow, GetControlValue (ghHScrollBar), GetControlValue (ghVScrollBar)); // update controls positions |
} |
// -------------------------------------------------------------------------- |
void MoveScroll (ControlHandle hScrollBar, short wDist) // update thumb position check for ends |
{ |
short wScrollPos = GetControlValue (hScrollBar); |
wScrollPos = wScrollPos + wDist; |
if ( wScrollPos < GetControlMinimum ( hScrollBar ) ) |
wScrollPos = GetControlMinimum ( hScrollBar ); |
else if ( wScrollPos > GetControlMaximum ( hScrollBar ) ) |
wScrollPos = GetControlMaximum ( hScrollBar ); |
SetControlValue (hScrollBar, wScrollPos); |
} |
// -------------------------------------------------------------------------- |
pascal void ProcScroll (ControlHandle hControl, short wPart) // handle scroll callback |
{ |
WindowPtr pWindow = (**hControl).contrlOwner; |
short wScrollDist = 0; |
switch (wPart) |
{ |
case kControlIndicatorPart: // scroll up |
wScrollDist = gStartValue - GetControlValue (hControl); |
break; |
case kControlUpButtonPart: // scroll up |
wScrollDist = -2; |
break; |
case kControlDownButtonPart: // scroll down |
wScrollDist = 2; |
break; |
case kControlPageUpPart: // page up |
if ( hControl == ghHScrollBar) |
wScrollDist = -(pWindow->portRect.right - pWindow->portRect.left - kPageOverlap); |
else |
wScrollDist = -(pWindow->portRect.bottom - pWindow->portRect.top - kPageOverlap); |
break; |
case kControlPageDownPart: // page up |
if ( hControl == ghHScrollBar) |
wScrollDist = (pWindow->portRect.right - pWindow->portRect.left - kPageOverlap); |
else |
wScrollDist = (pWindow->portRect.bottom - pWindow->portRect.top - kPageOverlap); |
break; |
} |
if ((wScrollDist) && (pWindow)) |
{ |
MoveScroll (hControl, wScrollDist); |
ScrollDrawContent (pWindow, GetControlValue (ghHScrollBar), GetControlValue (ghVScrollBar)); |
} |
} |
// -------------------------------------------------------------------------- |
void EndThumbTracking ( void ) // mouse up on thumb determine and set final value |
{ |
SetClip (gSaveClip); |
DisposeRgn (gSaveClip); |
SetControlValue (gControl, gSaveValue); |
gSaveValue = 0; |
return; |
} |
// -------------------------------------------------------------------------- |
SInt32 CalcValueFromPoint (ControlHandle hControl, Point thePoint) // figure where we are in scroll bar terms |
{ |
SInt32 theValue = 0, theRange, theDistance, thePin; |
Rect rectControl; |
WindowPtr pWindow; |
pWindow = (*hControl)->contrlOwner; |
rectControl = (*hControl)->contrlRect; |
theRange = GetControlMaximum ( hControl ) - GetControlMinimum ( hControl ); |
if ( hControl == ghHScrollBar) |
{ |
// Scroll distance adjusted for scroll arrows and the thumb |
theDistance = rectControl.right - rectControl.left - gTotalHSizeAdjust; |
// Pin thePoint to the middle of the thumb |
thePin = rectControl.left + (gScrollHThumbSize / 2); |
theValue = ((thePoint.h - thePin) * theRange) / theDistance; |
} |
else if ( hControl == ghVScrollBar) |
{ |
// Scroll distance adjusted for scroll arrows and the thumb |
theDistance = rectControl.bottom - rectControl.top - gTotalVSizeAdjust; |
// Pin thePoint to the middle of the thumb |
thePin = rectControl.top + (gScrollVThumbSize / 2); |
theValue = ((thePoint.v - thePin) * theRange) / theDistance; |
} |
theValue += gValueSlop; |
return theValue; |
} |
// -------------------------------------------------------------------------- |
pascal void ProcScrollThumbAction (void) // handle thumb callbacks |
{ |
Rect rectNull = {0, 0, 0, 0}; |
SInt32 theValue; |
WindowRef pWindow; |
ControlRef hControl = gControl; |
Point thePoint; |
Rect rectControl; |
pWindow = (*hControl)->contrlOwner; |
rectControl = (*hControl)->contrlRect; |
InsetRect (&rectControl, -kThumbTrackSlop, -kThumbTrackSlop); // expand control rect by tracking slop |
// Assumes the port is correctly set up |
GetMouse (&thePoint); |
if (PtInRect (thePoint, &rectControl)) |
theValue = CalcValueFromPoint (hControl, thePoint); // track new point point |
else |
theValue = gStartValue; // snap to start pos |
if (theValue != GetControlValue (hControl)) // if we scrolled |
{ |
SetClip (gSaveClip); |
gSaveValue = theValue; |
MoveScroll (hControl, theValue - GetControlValue (hControl)); // move the scroll bar and check edges |
ScrollDrawContent (pWindow, GetControlValue (ghHScrollBar), GetControlValue (ghVScrollBar)); // draw stuff in window |
gSaveValue = GetControlValue (hControl); |
GetClip (gSaveClip); |
ClipRect (&rectNull); |
} |
} |
// -------------------------------------------------------------------------- |
OSErr BeginThumbTracking (ControlRef hControl) // start of thumb record values and save clip setting current clip to null |
{ |
Rect rectNull = {0, 0, 0, 0}; |
OSErr theErr = noErr; |
Point thePoint; |
gControl = hControl; |
gStartValue = GetControlValue (hControl); |
gValueSlop = 0; |
GetMouse (&thePoint); |
gValueSlop = GetControlValue (hControl) - CalcValueFromPoint (hControl, thePoint); // delta from center |
gSaveClip = NewRgn (); |
GetClip (gSaveClip); |
ClipRect (&rectNull); |
return theErr; |
} |
// -------------------------------------------------------------------------- |
void DrawOneControlOffscreen (ControlHandle hControl) // draw a control into our offscreen port |
{ |
GDHandle hGDSave; |
CGrafPtr pCGrafSave; |
Point ptSave; |
short i = (**hControl).contrlRfCon; |
GetGWorld (&pCGrafSave, &hGDSave); |
SetGWorld ((CGrafPtr) gpGWOffScreen, NULL); |
if (((gPtCntlPos [i].v) != (**hControl).contrlRect.top) || ((gPtCntlPos [i].h) != (**hControl).contrlRect.left)) |
{ // reset control pos to original for offscreen update then restore it |
ptSave.v = (**hControl).contrlRect.top; |
ptSave.h = (**hControl).contrlRect.left; |
MoveControl (hControl, gPtCntlPos [i].h, gPtCntlPos [i].v); |
DrawControlInCurrentPort (hControl); // draw in offscreen |
MoveControl (hControl, ptSave.h, ptSave.v); |
} |
else // already in correct position |
DrawControlInCurrentPort (hControl); // draw in offscreen |
SetGWorld (pCGrafSave, hGDSave); |
} |
// -------------------------------------------------------------------------- |
void DoContentClick (WindowPtr pWindow, EventRecord * pEvent) |
{ |
GrafPtr pPortSave = NULL; |
Point pointClick; |
short partWindow = 0; |
ControlHandle hControlHit = NULL; |
ControlActionUPP myActionUPP = NewControlActionProc (ProcScroll); |
ControlActionUPP myThumbUPP = NewControlActionProc (ProcScrollThumbAction); |
GetPort (&pPortSave); |
SetPort ((GrafPtr) pWindow); |
pointClick = pEvent->where; |
GlobalToLocal (&pointClick); |
partWindow = FindControl(pointClick, pWindow, &hControlHit); |
if ((hControlHit == ghHScrollBar) || (hControlHit == ghVScrollBar)) |
{ |
gStartValue = GetControlValue (hControlHit); |
switch (partWindow) |
{ |
case kControlIndicatorPart: // live scroll |
if ( BeginThumbTracking (hControlHit) == noErr ) |
{ |
TrackControl ( hControlHit, pointClick, myThumbUPP); |
EndThumbTracking ( ); |
} |
break; |
case kControlUpButtonPart: // scroll up |
case kControlDownButtonPart: // scroll down |
case kControlPageUpPart: // page up |
case kControlPageDownPart: // page up |
partWindow = TrackControl (hControlHit, pointClick, myActionUPP); |
break; |
default: |
break; |
} |
if (hControlHit) |
{ |
if (GetControlValue (hControlHit) - gStartValue) // if we really did move our scroll bar |
InvalRect (&pWindow->portRect); // generate a window update |
} |
} |
else if (hControlHit) |
{ |
TrackControl(hControlHit, pointClick, (ControlActionUPP) -1); |
DrawOneControlOffscreen (hControlHit); // update our offscreen info |
} |
SetPort ((GrafPtr) pPortSave); |
} |
// -------------------------------------------------------------------------- |
void DoMenu (SInt32 menuResult) |
{ |
SInt16 theMenu; |
SInt16 theItem; |
Str255 daName; |
MenuRef theMenuHandle; |
theMenu = HiWord(menuResult); |
theItem = LoWord(menuResult); |
theMenuHandle = GetMenuHandle(theMenu); |
switch (theMenu) |
{ |
case kMenuApple: |
switch (theItem) |
{ |
default: |
OpenDeskAcc(daName); |
break; |
} |
break; |
case kMenuFile: |
switch (theItem) |
{ |
case kFileQuit: |
gDone = true; |
break; |
} |
break; |
} |
HiliteMenu(0); |
DrawMenuBar(); |
} |
// -------------------------------------------------------------------------- |
void DoEvent (void) |
{ |
EventRecord theEvent; |
SInt16 whatPart; |
SInt32 menuResult; |
WindowPtr whichWindow; |
SInt8 theKey; |
SInt8 theCode; |
Rect rectGrow; |
long grow; |
if (WaitNextEvent(everyEvent, &theEvent, gSleepTime, NULL)) |
{ |
switch (theEvent.what) |
{ |
case mouseDown: |
whatPart = FindWindow(theEvent.where, &whichWindow); |
switch (whatPart) |
{ |
case inGoAway: |
break; |
case inMenuBar: |
DrawMenuBar(); |
menuResult = MenuSelect(theEvent.where); |
if (HiWord(menuResult) != 0) |
DoMenu(menuResult); |
break; |
case inSysWindow: |
SystemClick(&theEvent, whichWindow); |
break; |
case inContent: |
if (whichWindow != FrontWindow ()) |
SelectWindow (whichWindow); |
else |
DoContentClick (whichWindow, &theEvent); |
break; |
case inDrag: |
DragWindow (whichWindow, theEvent.where, &(**LMGetGrayRgn()).rgnBBox); |
break; |
case inGrow: |
SetRect (&rectGrow, 100, 100, kOffScreenWidth + kScrollBarWidth, kOffScreenHeight + kScrollBarWidth); |
grow = GrowWindow (whichWindow, theEvent.where, &rectGrow); |
if (grow) |
{ |
SizeWindow (whichWindow, grow & 0x0000FFFF, grow >> 16, true); |
SetScrollParams (whichWindow); // reset scroll limits |
AdjustScrollBar (gpWindow, ghVScrollBar); // adjust and draw scroll bars |
AdjustScrollBar (gpWindow, ghHScrollBar); |
SetPort (whichWindow); |
InvalRect (&whichWindow->portRect); // redraw all |
} |
break; |
} |
break; |
case keyDown: |
case autoKey: |
theKey = theEvent.message & charCodeMask; |
theCode = (theEvent.message & keyCodeMask) >> 8; |
if ((theEvent.modifiers & cmdKey) != 0) |
{ |
menuResult = MenuKey(theKey); |
if (HiWord(menuResult) != 0) |
DoMenu (menuResult); |
} |
break; |
case updateEvt: |
BeginUpdate((WindowPtr) theEvent.message); |
DoUpdate((WindowPtr) theEvent.message); |
EndUpdate((WindowPtr) theEvent.message); |
break; |
case diskEvt: |
break; |
case osEvt: |
break; |
case kHighLevelEvent: |
AEProcessAppleEvent(&theEvent); |
break; |
} |
} |
else |
{ |
// idle tasks |
} |
} |
// -------------------------------------------------------------------------- |
void DrawOffScreen (CGrafPtr pCGOffScreen) |
{ |
GDHandle hGDSave; |
CGrafPtr pCGrafSave; |
Rect rectSource = (pCGOffScreen->portRect); |
RGBColor rgbGray = {0xC000, 0xC800, 0xD000}; |
short i; |
GetGWorld (&pCGrafSave, &hGDSave); |
SetGWorld (pCGOffScreen, NULL); |
// draw some background |
EraseRect (&rectSource); |
RGBForeColor (&rgbGray); |
PaintRect (&rectSource); |
MoveTo (rectSource.left, rectSource.top); |
LineTo (rectSource.right, rectSource.bottom); |
MoveTo (rectSource.right, rectSource.top); |
LineTo (rectSource.left, rectSource.bottom); |
// draw all my controls |
for (i = 0; i < kNumControls; i++) |
DrawControlInCurrentPort (ghControls[i]); // draw in offscreen (controls should not be scrolled here) |
SetGWorld (pCGrafSave, hGDSave); |
} |
// -------------------------------------------------------------------------- |
void SetScrollParams (WindowPtr pWindow) // set up scroll bars statics |
{ |
short windowHeight = pWindow->portRect.bottom - pWindow->portRect.top; |
short windowWidth = pWindow->portRect.right - pWindow->portRect.left; |
gScrollVThumbSize = windowHeight * (windowHeight - kScrollBarWidthAdjust - kScrollArrowWidth * 2) / kOffScreenHeight; // thumb size based on relative size of window to offscreen |
gScrollHThumbSize = windowWidth * (windowWidth - kScrollBarWidthAdjust - kScrollArrowWidth * 2) / kOffScreenWidth; // thumb size based on relative size of window to offscreen |
gTotalVSizeAdjust = ((kScrollArrowWidth * 2) + gScrollVThumbSize); // amount that scroll bar is less than full height of window |
gTotalHSizeAdjust = ((kScrollArrowWidth * 2) + gScrollHThumbSize); // amount that scroll bar is less than full height of window |
} |
// -------------------------------------------------------------------------- |
void AdjustScrollBar (WindowPtr pWindow, ControlHandle scrollBar) // sets up scroll settings and thumb |
{ |
short totalSize, viewSize; |
short windowHeight = pWindow->portRect.bottom - pWindow->portRect.top; |
short windowWidth = pWindow->portRect.right - pWindow->portRect.left; |
// get rect to determine if we are vert or horiz |
if (scrollBar == ghVScrollBar) |
{ // vertical |
totalSize= kOffScreenHeight - (windowHeight - kScrollBarWidthAdjust); // total doc. height - visable doc |
viewSize= windowHeight + kScrollBarWidth; // vis. doc. height |
MoveControl (scrollBar, windowWidth - kScrollBarWidthAdjust, -1); |
SizeControl (scrollBar, kScrollBarWidth, windowHeight + 2 - kScrollBarWidthAdjust); |
} |
else |
{ // horizontal |
totalSize= kOffScreenWidth - (windowWidth - kScrollBarWidthAdjust); // total doc. width - visable doc |
viewSize= windowWidth + kScrollBarWidth; // vis. doc. width |
MoveControl (scrollBar, -1, windowHeight - kScrollBarWidthAdjust); |
SizeControl (scrollBar, windowWidth + 2 - kScrollBarWidthAdjust, kScrollBarWidth); |
} |
// set the min, max, and current value of the scroll bar |
SetControl32BitMinimum (scrollBar, 0); |
SetControl32BitMaximum (scrollBar, totalSize); |
SetControl32BitValue (scrollBar, GetControlValue (scrollBar)); |
// set the scroll bar view size to create a proportional scroll box |
SetControlViewSize (scrollBar, viewSize); |
} |
// -------------------------------------------------------------------------- |
void InitToolbox(void) // standard inits |
{ |
MenuHandle menu; |
SInt16 modifiers = 0; |
EventRecord event; |
MaxApplZone (); |
InitGraf((Ptr) &qd.thePort); |
InitFonts(); |
InitWindows(); |
InitMenus(); |
TEInit(); |
InitDialogs(nil); |
InitCursor(); |
qd.randSeed = TickCount(); |
// init events |
EventAvail(everyEvent, &event); |
modifiers |= event.modifiers; |
EventAvail(everyEvent, &event); |
modifiers |= event.modifiers; |
EventAvail(everyEvent, &event); |
modifiers |= event.modifiers; |
// Init Menus |
menu = NewMenu (kMenuApple, "\p\024"); // new apple menu |
InsertMenu (menu, 0); // add menu to end |
AppendResMenu(menu, 'DRVR'); |
menu = NewMenu (kMenuFile, "\pFile"); // new menu |
InsertMenu (menu, 0); // add menu to end |
AppendMenu (menu, "\pQuit/Q"); // add items |
DrawMenuBar(); |
} |
// -------------------------------------------------------------------------- |
Boolean SetUp (void) // set up windows, controls, off screen |
{ |
short i; |
MenuHandle hMenu; |
Rect rectSize; |
InitToolbox (); |
SetRect (&gRectWindowGbl, 0, 0, kWindowWidth, kWindowHeight); |
OffsetRect (&gRectWindowGbl, kWindowOffset, kWindowOffset); |
gpWindow = NewCWindow (NULL, &gRectWindowGbl, "\pControl Scroll Test", false, kWindowGrowDocumentProc, (WindowPtr) -1, false, 0); |
SetScrollParams (gpWindow); |
SetRect (&rectSize, -1, kWindowHeight - kScrollBarWidthAdjust, kWindowWidth + 1 - kScrollBarWidthAdjust, kWindowHeight + 1); |
ghHScrollBar = NewControl (gpWindow, &rectSize, "\p", false, 0, 0, 0, kControlScrollBarProc, 0); |
if (!ghHScrollBar) |
return false; |
AdjustScrollBar (gpWindow, ghHScrollBar); |
ShowControl (ghHScrollBar); |
SetRect (&rectSize, kWindowWidth - kScrollBarWidthAdjust, -1, kWindowWidth + 1, kWindowHeight + 1 - kScrollBarWidthAdjust); |
ghVScrollBar = NewControl (gpWindow, &rectSize, "\p", false, 0, 0, 0, kControlScrollBarProc, 0); |
if (!ghVScrollBar) |
return false; |
AdjustScrollBar (gpWindow, ghVScrollBar); |
ShowControl (ghVScrollBar); |
hMenu = NewMenu (kButtonMenuID, "\pButton"); // new menu |
AppendMenu (hMenu, "\pItem 1;Item 2;Item 3;Item 4"); // add items |
InsertMenu (hMenu, hierMenu); // add menu to end |
for (i = 0; i < kNumControls; i++) |
{ |
short top = 10 + (abs (Random ()) % (kOffScreenHeight - kScrollBarWidth - 10 - 20)); |
short left = 10 + (abs (Random ()) % (kOffScreenWidth - kScrollBarWidth - 10 - 75)); |
SetRect (&rectSize, left, top, left + 75, top + 20); |
// NOTE: intial pos is stored in gPtCntlPos array to allow reference during scrolling |
ghControls [i] = NewControl (gpWindow, &rectSize, "\p", true, 0, kButtonMenuID, 0, popupMenuProc, i); |
if (!(ghControls [i])) |
return false; |
gPtCntlPos [i].v = rectSize.top; |
gPtCntlPos [i].h = rectSize.left; |
} |
SetRect (&rectSize, 0, 0, kOffScreenWidth, kOffScreenHeight); |
if (NewGWorld (&gpGWOffScreen, 32, &rectSize, NULL, NULL, 0) != noErr) |
return false; |
DrawOffScreen ((CGrafPtr) gpGWOffScreen); |
ShowWindow (gpWindow); |
return true; |
} |
// functions (external/public) ----------------------- ---------------------- |
int main (void) |
{ |
if (SetUp ()) |
while (!gDone) |
DoEvent (); |
CleanUp (); |
return 0; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-30