NO

Author Topic: Integrating Custom Controls in PellesC - porting the MS sample SpinCube  (Read 3184 times)

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 1769
The PellesC documentation contains pratically nothing about custom controls integration in the IDE.
Basically PellesC behaves as the dialog editor of MSVC++.
To find documentation around is very difficult because MS pushes to use technologies based on automation interface and removed everything from its databases.  >:(
What remains is in comments of 'custcntl.h' in its MS version (PellesC version has been stripped of all comments). You can find it in the Win7 SDK.
I don't want discuss here how you can create a custom control, for which there are better tutorials around (i.e. on catch22), but just spend few words on optional service routines required to integrate your custom control in the dialog editor of PellesC (and of MSVC++ which is the same).

All you need to interact with the dialog editor is a function that gives all necessary information to the editor, this function is 'CustomControlInfo'.
The editor will search for such function in the custom control DLL (and also for its variants: 'CustomControlInfoA' and 'CustomControlInfoW' for unicode). If the function is not found in the DLL you will get an error message saying that this is not a custom control DLL!.
The prototype of this function is:
Code: [Select]
UINT CALLBACK CustomControlInfo(LPCCINFO acci)It requires a valid pointer to a memory area large enough to hold an array of descriptive structures 'acci', and returns the number of custom controls in the DLL.
The normal procedure is to call first the function with a null pointer to get only the number of controls in the library, then allocate memory and call again the function to collect controls data:
Code: [Select]
    int n = CustomControlInfo(NULL);
    LPCCINFO p_acci = malloc(n * sizeof(CCINFO));
    CustomControlInfo(p_acci);
Now we have an array of 'n' elements of custom controls info structures pointed by p_acci.
Wait, but we are on the other side! the editor call our routine 'CustomControlInfo', and we have to answer correctly!
So when we get a call to our 'CustomControlInfo' with a null parameter we return the number of controls in our library, if the parameter is a valid pointer we fill in the array with appropriate controls data.
Code: [Select]
UINT CALLBACK CustomControlInfo (LPCCINFO acci)
{
  if (!acci)  // Editor is querying the number of controls this DLL supports, so return the number.
    return NCONTROLS;

  //
  // Else we can fill in the constant calues.
  //

  for (int i=0; i<NCONTROLS; i++)
  {
      acci[i].flOptions         = 0;
      acci[i].cxDefault         = 40;      // default width  (dialog units)
      acci[i].cyDefault         = 40;      // default height (dialog units)
      acci[i].flStyleDefault    = WS_CHILD | WS_VISIBLE;

       ...           //Fill the structure

  }

  //
  // Return the number of controls that the DLL supports
  //

  return NCONTROLS;
}

One of the elements of a custom control info's is the styles that the control supports. These informations are passed in two fields of info structure:
Code: [Select]
    INT     cStyleFlags;                // Entries in the following style table.
    LPCCSTYLEFLAG aStyleFlags;         // Points to style flag table.
You have prebuild the array of styles to have it ready to pass:
Code: [Select]
CCSTYLEFLAG aSpincubeStyleFlags[] = { { SS_ASTYLE,    0, TEXT("SS_ASTYLE")    },
                                      { SS_ANOTHERSTYLE, 0, TEXT("SS_ANOTHERSTYLE") } };
The info structures contains also two procedures, one to set styles of the control and the other to adjust control window dimension according to the text to show.
The first allows to change in the dialog editor the properties (styles) of the control, the other calculates the dimensions taking into account graphical elements of your custom control. Of course these can be NULL if you don't need them.
This is the MS definition and description of them:
Code: [Select]
/*
 * The SizeToText function prototype.  This will be called if the user
 * requests that the custom control be sized to fit it's text.  It
 * should use the specified styles, text and font to determine how
 * large the control must be to accommodate the text, then return this
 * value in pixels.  The value of -1 should be returned if an error
 * occurs.
 */
typedef INT (CALLBACK* LPFNCCSIZETOTEXT)(DWORD flStyle, DWORD flExtStyle,HFONT hfont, LPSTR pszText);

/*
 * The Style function prototype.  This will be called when the user
 * wants to edit the styles of a custom control.  It should display a
 * dialog to edit the styles, update the styles in the pccs structure,
 * then return TRUE for success.  If an error occurs or the user
 * cancels the dialog, FALSE should be returned.
 */
typedef BOOL (CALLBACK* LPFNCCSTYLE)(HWND hwndParent,  LPCCSTYLEA pccs);

Now on the PellesC IDE side  :(
PellesC custom control management is available only when a dialog is under editing  >:(, so you have to open a dialog to see the menu entry 'Dialog'. Here you have three choises: 'Open custom control', 'Remove Custom control', 'New Custom control'.
The first allows you to load a custom control DLL, the second allows to remove an already loaded control and with the last you can manually define a custom control (basically you give some info normally contained in the 'acci' structure as class name, flags, etc. No helper functions will be available, nor preview).
Once you loaded a custom control DLL you can have preview and double clicking on styles setting of control properties will open the custom control style editing function.

To verify this pratically I attach the PellesC port of the well known MS sample 'SpinCube' that you can still find in Win7 SDK.
Compile the entire workspace (project->Rebuild Workspace), then open a dialog somewhere, choose 'Open custom control', select the 'SpinCube.dll' and load it.
Now selecting 'SpinTest' as active project you can open dialogs, preview them and change styles!  8)

I'm sure it's not exhaustive (and even not very clear ?  :(), but if you still have questions .... I'll try to answer.

P.S. BORLAND added some other custom functions to interact with its IDE. We don't care about them... ;)

EDIT: Modified project files for eventual library location problems.
« Last Edit: August 09, 2014, 06:44:00 pm by frankie »

JohnF

  • Guest
Re: Integrating Custom Controls in PellesC - porting the MS sample SpinCube
« Reply #1 on: August 08, 2014, 05:39:58 pm »
Looks like it could be good,

Couldn't find spincube.lib so I added

#pragma lib("../spincube.lib")

which fixed that. Then these

POLINK: error: Unresolved external symbol '__imp__giNumSpincubesThisProcess'.
POLINK: error: Unresolved external symbol '__imp__giNumSpincubesAllProcesses'.
POLINK: fatal error: 2 unresolved external(s).

John


Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 1769
Re: Integrating Custom Controls in PellesC - porting the MS sample SpinCube
« Reply #2 on: August 09, 2014, 04:44:12 pm »
John I tested again the project, it compiles ok.
In the SpinTest project the folder for SpinCube.lib is included, I don't know why you have these problems  ???
Have you rebuilt workspace from Project->Rebuild Workspace ? If you tried to build SpinTest before SpinCube, the lib will be missing.
« Last Edit: August 09, 2014, 04:58:22 pm by frankie »

czerny

  • Guest
Re: Integrating Custom Controls in PellesC - porting the MS sample SpinCube
« Reply #3 on: August 09, 2014, 05:12:41 pm »
I tried it with 7 rc 3 and it works ok!

JohnF

  • Guest
Re: Integrating Custom Controls in PellesC - porting the MS sample SpinCube
« Reply #4 on: August 09, 2014, 05:26:59 pm »
Started from scratch, re-unzipped the file SpinCube_workspace.zip to new folder and rebuilt workspace. I still get problems.

- - - - - - - - - - SpinTest.exe
Building SpinTest.obj.
Building SpinTest.res.
Building SpinTest.exe.
POLINK: fatal error: File not found: 'spincube.lib'.
*** Error code: 1 ***

Made sure the lib was found,  then, the test app can't find the dll.

Copied the dll to the right folder and then it worked.

Good demo anyway.

I can't understand why the differences though.

John

 

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 1769
Re: Integrating Custom Controls in PellesC - porting the MS sample SpinCube
« Reply #5 on: August 09, 2014, 05:44:19 pm »
Thanks John.
Please have a look to the workspace and projects options. The workspace dependencies is set to build 'SpinCube' project before the 'SpinTest' one. So if you restart it from scratch, open the 'SpinCube.ppw' workspace then from IDE menu hit Project-->Rebuild_Workspace it should compile automatically with no problems.
I have set the SpinTest.exe as executable helper in the 'SpinCube' project, if you set it as active project you can run the test executable simply clicking the execute button.
To run SpinTest.exe from its directory you have to copy the SpinCube.Dll in the executable directory.

JohnF

  • Guest
Re: Integrating Custom Controls in PellesC - porting the MS sample SpinCube
« Reply #6 on: August 09, 2014, 06:06:27 pm »
Thanks John.
Please have a look to the workspace and projects options. The workspace dependencies is set to build 'SpinCube' project before the 'SpinTest' one. So if you restart it from scratch, open the 'SpinCube.ppw' workspace then from IDE menu hit Project-->Rebuild_Workspace it should compile automatically with no problems.
I have set the SpinTest.exe as executable helper in the 'SpinCube' project, if you set it as active project you can run the test executable simply clicking the execute button.
To run SpinTest.exe from its directory you have to copy the SpinCube.Dll in the executable directory.

Well, started from scratch again, started the .ppw - you can see from the text below that SpinCube is compiled first. The same problem persists.

================
- - - - - - - - - - SpinCube.dll
Building Paint.obj.
Building SpinCube.obj.
Building SpinCube.res.
Building SpinCube.dll.
Creating object: ...\SpinCube_workspace\SpinCube.exp
Creating library: ...\SpinCube_workspace\SpinCube.lib
- - - - - - - - - - SpinTest.exe
Building SpinTest.obj.
Building SpinTest.res.
Building SpinTest.exe.
POLINK: fatal error: File not found: 'spincube.lib'.
*** Error code: 1 ***
==================

In the .ppw

PROJECT = SpinTest\SpinTest.ppj
PROJECT = SpinCube.ppj

DEPENDENCY = SpinTest\SpinTest.ppj ON SpinCube.ppj

John

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 1769
Re: Integrating Custom Controls in PellesC - porting the MS sample SpinCube
« Reply #7 on: August 09, 2014, 06:39:12 pm »
I understood.
In the 'SpinTest.ppj' project file the library folders are defined as:
Code: [Select]
LIB = $(PellesCDir)\Lib\Win;$(PellesCDir)\Lib;..\..\SpinCube#
But you named the folder 'SpinCube_workspace' so it will not find library's folder.
A working, and much more general, definition could be:
Code: [Select]
LIB = $(PellesCDir)\Lib\Win;$(PellesCDir)\Lib;..#
The simplest way requires that you select the project 'SpinTest' in your installation, open the project options go to the folder tab and remove the folder 'SpinCube', than insert it again this now should point to your real installation directory....

P.S. I modified also the project in the first post of the thread, you can check it.
« Last Edit: August 10, 2014, 11:44:18 am by frankie »

JohnF

  • Guest
Re: Integrating Custom Controls in PellesC - porting the MS sample SpinCube
« Reply #8 on: August 09, 2014, 08:33:37 pm »
Your modified zip worked ok, thanks.

John