fredley
fredley

Reputation: 33931

How can I get my callback function to work?

I'm getting monitor information using EnumDisplayMonitors:

BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData){
  Class::callback(hMonitor,hdcMonitor,lprcMonitor,dwData);
  return true;
}

bool Class::callback(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData){
  classVar.appendData("callback");
  return true;
}

bool Class::f(){
  ...
  EnumDisplayMonitors(NULL,NULL,MonitorEnumProc,NULL);
  ...
}

Class::callback is static (if it isn't I get error C2352: illegal call of non-static function). This however causes problems with classVar: error C2228: left of '.appendData must have class/struct/union'. What should I be doing here to get around this problem (I want the callback to write data to classVar)?

Upvotes: 3

Views: 2090

Answers (4)

Coffee on Mars
Coffee on Mars

Reputation: 998

I sometimes have this problem, and usually solve it through function objects, they are more versatile that static functions, and you can create one which can memorize any parameter before being passed to MonitorEnumProc.

Upvotes: 0

Dialecticus
Dialecticus

Reputation: 16769

Use LPARAM dwData to provide pointer to the object. If there's more data to provide to callback then use auxiliary struct to put all data together and pass pointer to this struct.

BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
  ((Class*)dwData)->callback(hMonitor,hdcMonitor,lprcMonitor);
  return true;
}

bool Class::callback(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor)
{
  classVar.appendData("callback");
  return true;
}

bool Class::f()
{
  ...
  EnumDisplayMonitors(NULL,NULL,MonitorEnumProc, (LPARAM)this);
  ...
}

EDIT: With auxiliary struct:

BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
  Class theClass = ((Auxiliary*)dwData)->theClass;
  RestOfData theRest = ((Auxiliary*)dwData)->theRest;

  theClass->callback(hMonitor,hdcMonitor,lprcMonitor, theRest);
  return true;
}

bool Class::callback(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, RestOfData* theRest)
{
  // use theRest
  classVar.appendData("callback");
  return true;
}

bool Class::f()
{
  ...
  Auxiliary theBundle(this, theRest);
  EnumDisplayMonitors(NULL,NULL,MonitorEnumProc, (LPARAM)theBundle);
  ...
}

Upvotes: 2

André Caron
André Caron

Reputation: 45274

The last parameter of EnumDisplayMonitors() is an extra pointer reserved for use by the caller. It is passed uninterpreted to the callback function. Pass a pointer to the class instance.

BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData){
  reinterpret_cast<Class*>(dwData)->callback(hMonitor,hdcMonitor,lprcMonitor);
  return true;
}

bool Class::callback(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor){
  classVar.appendData("callback");
  return true;
}

bool Class::f(){
  ...
  EnumDisplayMonitors(NULL,NULL,MonitorEnumProc,reinterpret_cast<LPARAM>(this));
  ...
}

Upvotes: 4

cli_hlt
cli_hlt

Reputation: 7164

You can use the dwData argument to pass in a pointer to your class instance, i.e. something like this (note: callback won't need to be static anymore - actually it becomes obsolete):

BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData){
  ((Class*)dwData)->callback(hMonitor,hdcMonitor,lprcMonitor);
  return true;
}

bool Class::callback(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor){
  appendData("callback");
  return true;
}

bool Class::f(){
  ...
  EnumDisplayMonitors(NULL,NULL,MonitorEnumProc,this);
  ...
}

Upvotes: 1

Related Questions