|
||||||
| C and C++ C and C++ forum for discussing all forms of C except for C#. These languages are powerful low level languages used for creating Operating Systems, Device Drivers, compilers and much more. |
![]() |
|
|
LinkBack | Thread Tools | Search this Thread | Display Modes |
|
|||
|
I'm creating a set of classes that mimic standard VC controls (such as command buttons, etc.) on the console. My base class, ConsoleObject, works beautifully. I added a few function pointers that can be set to handle events:
Code:
void (*onFocusEventHandler)(void); void (*onLoseFocusEventHandler)(void); void (*onClickEventHandler)(unsigned __int32 mouseX,unsigned __int32 mouseY,unsigned __int8 button); void (*onDoubleClickEventHandler)(unsigned __int32 mouseX,unsigned __int32 mouseY,unsigned __int8 button); void (*onMouseOverEventHandler)(unsigned __int32 mouseX,unsigned __int32 mouseY); void (*onMouseOutEventHandler)(unsigned __int32 mouseX,unsigned __int32 mouseY); void (*onDestroyEventHandler)(void); cannot convert from 'void (__thiscall WindowTitleBar::*)(unsigned __int32,unsigned __int32,unsigned __int8)' to 'void (__cdecl *)unsigned __int32,unsigned __int32,unsigned __int8)' Typecasting didn't work. I tried using template classes, but then the WindowTitleBar can't set the handler functions (which belong to WindowTitleBar) to the command buttons (also derived from ConsoleObject)that they're for. I get the following error: cannot convert from 'void (__thiscall WindowTitleBar::* )(unsigned __int32,unsigned __int32,unsigned __8)' to 'void (__thiscall CommandButton::* )(unsigned __int32,unsigned __int32,unsigned __8)' In addition, when a derived class Window tries to instantiate a variable of type WindowEventHandler which is not derived from ConsoleObject, I get illogical compile errors: Code:
eventHandler = new WindowEventHandler(objects,this); /* Note that WindowEventHandler has a constructor: WindowEventHandler(ConsoleObject<Object> **objList,ConsoleObject<Window> *parent) */ 'WindowEventHandler::WindowEventHandler(ConsoleObj ect<objClass> **,ConsoleObject<Window> *)' : cannot convert parameter 1 from 'ConsoleObject<objClass> **' to 'ConsoleObject<objClass> **' Last time I checked, ConsoleObject<objClass> ** and ConsoleObject <objClass> ** are the same thing. Can someone please help me? I know this is confusing, and real GUIs are much more efficient, but I just like doing things myself and this is a major obstacle for me. I'm attaching the source code to this post. (It's a header (.h) file, but I had to change the extension to .txt to upload it.) I have a bad habit of not documenting my code very well, so if you need further clarification, just let me know.) Thanks in advance. Last edited by dargueta; 10-17-2007 at 09:08 PM. |
| Sponsored Links |
|
|
|
|||
|
Had a quick look at your code. Correct me if I'm wrong, but function members can only point to function members of the same base class or the same concrete class, and minimize and titlebar are different concrete classes, therefore this is invalid as minimize and titlebar point to different classes.
Quote:
|
|
|||
|
That's what I was trying to work around. Is there any way to typecast the function to force it to work? I read something somewhere that there's a way to force the __thiscall declarator to disappear by using something like this.this->foo(). It didn't seem to help.
|
|
|||
|
I don't think you can. Even if it does work, it's not a safe cast. The behaviour would be unpredictable depending on the compiler. And that's bad! Best way to approach this is to use a different design. Polymorphic functions would work better.
|
|
|||
|
I want the user to be able to specify their own functions for the handlers, so __declspec(__stdcall) __cdecl pointers would be ideal. The problem is that classes derived from ConsoleObject use the __thiscall calling convention. I'm guessing I'd use a template for the argument types...? Perhaps something like this is what you meant?
Code:
template <typename funcPtrType>
void onMouseOver(funcPtrType (*p)(void))
{
if(p != NULL)
(*p)();
else
//default handler goes here
}
|
| Sponsored Links |
|
|
|
|||
|
Do you mean an abstract class? I've never done that; could you show me a simple example, please? I'm a more visual person.
You'd think after programming in C++ for four years I'd have come across this before... |
|
|||||
|
Sure. I wrote this for a scenario that includes a button. When the button is pressed, it raises an event.
The abstract class is called IButtonEvents. It is the interface between the Button class and, in this instance, the SomeEventHandler class. Here is the header for IButtonEvents: Code:
#pragma once
class IButtonEvents
{
public:
virtual ~IButtonEvents(); // Virtual Destructor.
// Purpose: Function declaration for function thats represents an event. Must be overridden in
// a derived class.
//---------------------------------------------------------------------------------------------------
virtual void _OnPress() = 0; // Is raised when a button is pressed.
};
Code:
#include "IButtonEvents.h"
IButtonEvents::~IButtonEvents()
{
}
Code:
#pragma once
#include <iostream>
#include "IButtonEvents.h"
using namespace std;
class SomeEventHandler : public IButtonEvents
{
private:
void _OnPress(); // The overidden function of the inherited virtual function.
// AKA, the EventHandler.
};
Code:
#include "SomeEventHandler.h"
void SomeEventHandler::_OnPress()
{
// Display a response message identifying the object and the event.
cout << "Object at " << this << " responding to _OnPress event." << endl;
}
Code:
#pragma once
#include "IButtonEvents.h"
class Button
{
private:
struct EventHandlerRecord // The record structure for the table of EventHandlers
{
IButtonEvents * Object; // Pointer to an EventHandling object
EventHandlerRecord * NextRecord; // Pointer to the next record
};
EventHandlerRecord * FirstRecord; // The pointer to the first record
EventHandlerRecord * LastRecord; // The pointer to the last record
public:
Button::Button(); // Default Constructor
Button::~Button(); // Default Destructor
// Parameters: A pointer to an object derived from the IButtonEvent class.
// Purpose: Adds a record the EventHandler table.
//-----------------------------------------------------------------------------------
void AddEventHandler(IButtonEvents * EventHandlerObject);
// Purpose: Raises the _OnPress event function
//-----------------------------------------------------------------------------------
void Press();
};
Code:
#include "Button.h"
Button::Button()
{
/* ===Initialize pointers=== */
Button::FirstRecord = 0;
Button::LastRecord = 0;
}
Button::~Button()
{
/* ===Destroy the EventHandler table=== */
// create a cursor
Button::EventHandlerRecord * cursor;
// while a record exists . . .
while (Button::FirstRecord != 0)
{
// . . . point the cursor to the first record
cursor = Button::FirstRecord;
// move the FirstRecord to the next record
Button::FirstRecord = Button::FirstRecord->NextRecord;
// delete the record at the cursor
delete cursor;
}
}
void Button::AddEventHandler(IButtonEvents * EventHandlerObject)
{
// Create a cursor
Button::EventHandlerRecord * cursor;
// Create a new record
cursor = new Button::EventHandlerRecord;
// Set the Object field
cursor->Object = EventHandlerObject;
// If the first record hasn't been assigned yet . . .
if (FirstRecord == 0)
{
// . . . make the new record the first record
Button::FirstRecord = cursor;
}
// Else . . .
else
{
// . . . append the record to the last record
Button::LastRecord->NextRecord = cursor;
}
// Make the new record the last record
cursor->NextRecord = 0;
Button::LastRecord = cursor;
}
void Button::Press()
{
/* ===Call the _OnPress function for each object in the EventHandler table=== */
// Create a cursor
Button::EventHandlerRecord * cursor;
// Start at the first record
cursor = Button::FirstRecord;
// While the cursor points to a record . . .
while (cursor != 0)
{
// . . . Call the _OnPress function for that object
cursor->Object->_OnPress();
// Move to the next record
cursor = cursor->NextRecord;
}
}
Code:
#include <iostream>
#include "Button.h"
#include "SomeEventHandler.h"
using namespace std;
int main()
{
Button myButton; // Button object
SomeEventHandler * EventHandler1 = new SomeEventHandler; // An event handler object
SomeEventHandler * EventHandler2 = new SomeEventHandler; // Another event handler object
// Add the EventHandlerObjects to myButton's EventHandler table
myButton.AddEventHandler(EventHandler1);
myButton.AddEventHandler(EventHandler2);
// Press the button
myButton.Press();
// Wait for the new line character
cin.get();
// Destroy the EventHandler objects
delete EventHandler2;
delete EventHandler1;
return 0;
}
|
|
|||
|
I went with some of your suggestions, and it seems to work all right. Now I have a new problem. In my base class, ConsoleObject, there is a pointer variable called parent that is of type Window, which is declared later on in the file. The compiler chokes because it doesn't recognize the type. How can I work around this?
|
![]() |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | Search this Thread |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Issue writing to file: pointer to a class which contains pointers to other classes | Sheemer | C and C++ | 0 | 08-21-2007 01:17 AM |
| multi-pass preprocessing | kenna | C and C++ | 11 | 08-14-2007 10:45 AM |
| Reg Fucntion pointers | sowmi | C and C++ | 9 | 07-29-2007 03:29 AM |
| small help in this generator function plz | SamehSpiky | C and C++ | 3 | 06-22-2007 11:47 AM |
| Xav | ........ | 1097.16 |
| MeTh0Dz|Reb0rn | ........ | 986.37 |
| morefood2001 | ........ | 850.04 |
| John | ........ | 841.93 |
| WingedPanther | ........ | 684.54 |
| marwex89 | ........ | 638.26 |
| Brandon W | ........ | 493.36 |
| chili5 | ........ | 292.12 |
| Steve.L | ........ | 188.37 |
| orjan | ........ | 187.41 |
Goal: 100,000 Posts
Complete: 79%