How to Call a Custom CDEF or WDEF

by Carolyn Zichterman


[Intro] [Demos] [Download] [How to Call] [Build Instr]

CDEF Introduction

Zig gets asked quite frequently to describe how to call a custom control definition (CDEF), such as Zig's Greyscale Buttons. This section gives the basic process. You may want to read more about the Control Manager in Inside Macintosh. We assume a rudimentary knowledge of the Toolbox and Mac OS. Variant useWFont refers to kControlUsesOwningWindowsFontVariant.

The procID

First calculate the procID for the Control resource (CNTL). The procID is defined as:

procID = (16 * CDEF ID) + variation code

where the CDEF ID equals 1000.

Control Manager variation (codes) are:

For example, to calculate the procID for a radio button:

procID = (16 * 1000) + 2 = 16002.

To calculate the procID for a radio button that uses the window font instead of the system font:

procID = (16 * 1000) + 2 + 8 = 16010.

Then plug this parameter in Control Manager functions, such as NewControl() and GetNewControl(), in Dialog Boxes and Alerts, and in PowerPlant Constructor resources as described below.

Control Manager Code

Controls are onscreen objects, such as buttons, checkboxes, and radio buttons, that the user operates with the mouse. The Control Manager creates and manages controls, using the NewControl() and GetNewControl() functions. CDEFs determine how controls look and act.

NewControl

You may create controls using the NewControl() function. Change the procID parameter after calculating as shown above.

/*
  NewControl() code example
  
  This routine takes a LOT of parameters and
  creates a radio button out of them.
*/
#include <Controls.h>

ControlRef
MyCreateRadioButton(
  // window in which the new control will appear
  const WindowRef   inWindow,        
  // initial location and size of control
  const Rect &      inBoundsRect,    
  // control's initial title string
  ConstStr255Param  inControlTitle,  
  // show the control as soon as it's created?
  const Boolean     inVisible,       
  // initial value (0=off, 1=on, 2=tristated)
  const SInt16      inInitialValue,  
  // maximum control value (use 0)
  const SInt16      inMinValue,      
  // minimum control value (use 1 or 2)
  const SInt16      inMaxValue,      
  // anything you like
  const SInt32      inRefCon )       
{  
  // for this example, use 'CDEF' resource ID 1000 
  const SInt16  cdefID  = 1000;

  // for this example, create a radio button,
  // and use the window font to draw its title
  const SInt16  variationCode
    = radioButProc + kControlUsesOwningWindowsFontVariant;
  
  // calculate the correct procID
  const SInt16  procID  = ( 16 * cdefID ) + variationCode;
  
  // use the procID in a call to NewControl()
  ControlRef  control  = ::NewControl( inWindow, &inBoundsRect,
    inControlTitle, inVisible, inInitialValue, 
    inMinValue, inMaxValue, procID, inRefCon );
  
  // return the newly created control
  return control;
}

GetNewControl

You may also create controls from descriptions in CNTLs using the GetNewControl() function. GetNewControl() creates control records from CNTLs, adds them to the control list for the current window, and returns a control handle for each control.

/*
  GetNewControl() code example

  This routine just takes two parameters: a 'CNTL' resource ID
  and a window into which the new control goes.
  
  See the ResEdit screenshot to see the procID.
  
  You would usually call GetNewControl() directly instead
  of having such a mindless function.
*/
#include <Controls.h>

ControlRef
MyCreateRadioButtonFromResource(
  const SInt16     inCNTLid,
  const WindowRef  inWindow )
{
  // all the control's information, including the procID,
  // is read from the 'CNTL' resource with id inCNTLid
  ControlRef  control  = ::GetNewControl( inCNTLid, inWindow );
  return control;
}

Dialog Boxes and Alerts

In dialog boxes and alerts, Dialog Manager routines call Control Manager routines to implement controls such as buttons, checkboxes, and radio buttons. Use CNTLs to create controls such as icon buttons and indenting buttons and to change the button font.

PowerPlant Resources

Using Metrowerks PowerPlant, implement PowerPlant object (PPob) resources with Constructor.

Constructor

PowerPlant Constructor edits PPob resources, which specify window elements or controls. To see where to enter the procID:

  1. Launch Constructor and Open Zig's Greyscale Demo/PP.
  2. Under Windows and Views, double-click on Push Buttons.
  3. Double-click on the Enabled button; the procID is entered in the Control Kind field in this window.
  4. Calculate the procID as shown above.
  5. Change the procID to call these controls.

PowerPlant variation (codes) are:

To use a font other than the system font, change it in the Text Traits ID pop-up menu. Be sure not to add variation code to the procID.

WDEF Introduction

This section explains how to call a custom window definition (WDEF), such as Zig's Greyscale Windows. You may want to read more about the Window Manager in Inside Macintosh.

The procID

First calculate the procID for the Window resource (WIND). The procID is defined as:

procID = (16 * WDEF ID) + variation code

where the WDEF ID equals 1000.

Window Manager variation (codes) are:

For example, to calculate the procID for a movable modal dialog:

procID = (16 * 1000) + 5 = 16005.

Then plug this parameter in Window Manager functions, such as NewWindow() and GetNewWindow(), in WIND resources, and in PowerPlant resources (using Constructor) as described below.

Window Manager Code

The Window Manager creates and manages windows, using the NewWindow() and GetNewWindow() functions. WDEFs determine how windows look.

NewWindow

You may create windows using the NewWindow() function. Change the procID parameter after calculating as shown above.

/*
	NewWindow() sample code
	
	Sample code shows where to put the procID for a window
	created via NewControl()	
*/
WindowRef
MyCreateWindow(
	// usually NULL, where to store the window record
	// NULL ==> let Window Manager allocate it
	void *			inStorage,
	// global bounds of the new window
	const Rect &		inWindowBounds,
	// the window title
	ConstStr255Param	inWindowTitle,
	// show the window immediately upon creation?
	const Boolean		inVisible,
	// window to position the new window behind, -1 for frontmost
	WindowRef		inBehind,
	// only applies to documentProc windows
	const Boolean		inHasCloseBox,
	// whatever you want
	SInt32			inRefCon )
{
	// calculate the window procID	
	const SInt16	wdefID		= 1000;	// for this example
	const SInt16	variationCode	= documentProc;
	const SInt16	procID		= ( 16 * wdefID ) + variationCode;
	
	// create the window
	WindowRef	window
		= ::NewWindow( inStorage, &inWindowBounds,
			inWindowTitle, inVisible, procID,
			inBehind, inHasCloseBox, inRefCon );
	
	return windowRef;
}

GetNewWindow

You may also create windows from descriptions in WIND resources using the GetNewWindow() function. GetNewWindow() creates window records from WINDs.

/*
	GetNewWindow() sample
	
	Shows how to create a window with a
	'WIND' resource. 
	
	See the ResEdit screenshot to see the procID.
	
	You would normally call GetNewWindow() directly
	instead of having such a mindless function.
*/
WindowRef
MyCreateNewWindow(
	// resource ID of a 'WIND' resource
	const SInt16	inWINDid,
	// where to store the window record, usually NULL
	// NULL ==> let the Window Manager allocate it
	void *		inStorage,
	// Which window to position behind, -1 for frontmost
	WindowRef	inBehind )
{
	WindowRef	window	= ::GetNewWindow( inWINDid, inStorage, inBehind );
	return window;
}

WIND Resource

Replace the number as shown in the dialog box below with the calculated procID.

PowerPlant Resources

Using Metrowerks PowerPlant, implement PowerPlant object (PPob) resources with Constructor.

Constructor

PowerPlant Constructor edits PPob resources, which specify window elements. To see where to enter the procID:

  1. Launch Constructor and Open Zig's Greyscale Demo/PP.
  2. Under Windows and Views, double-click on Document.
  3. Double-click on the window frame.

PowerPlant variation (codes) are: