Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / Managed C++ / September 2007

Tip: Looking for answers? Try searching our database.

CALLBACK procedure (invalid calling convention '__stdcall ' for function compiled with /clr:pure or /clr:safe)

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
SQACPP - 16 Sep 2007 06:56 GMT
Hi,

I try to figure out how to use Callback procedure in a C++ form
project

The following code *work* perfectly on a console project

#include "Windows.h"
BOOL CALLBACK MyEnumWindowsProc(HWND hwnd, LPARAM lparam)
{
 // blablabla we dont care for now
return (TRUE);
}
int main()
{
   EnumWindows((WNDENUMPROC) MyEnumWindowsProc,0);
}

But in the C++ form project it return the following error :

Error C3641: 'MyEnumWindowsProc' : invalid calling convention
'__stdcall ' for function compiled with /clr:pure or /clr:safe

I already read a lot of post on the subject but still trying to find
an answer...

Thanks!

Mike
Jochen Kalmbach [MVP] - 16 Sep 2007 07:06 GMT
Hi SQACPP!

> Error C3641: 'MyEnumWindowsProc' : invalid calling convention
> '__stdcall ' for function compiled with /clr:pure or /clr:safe

Switch the setting in your project to:
"Common language runtime support" to "/clr"

Signature

Greetings
  Jochen

   My blog about Win32 and .NET
   http://blog.kalmbachnet.de/

SQACPP - 16 Sep 2007 08:06 GMT
On Sep 16, 2:06 am, "Jochen Kalmbach [MVP]" <nospam-
Jochen.Kalmb...@holzma.de> wrote:
> Hi SQACPP!
>
[quoted text clipped - 10 lines]
>     My blog about Win32 and .NET
>    http://blog.kalmbachnet.de/

Thanks! it work with /clr

I'm wondering one another thing about CALLBACK functions....

By example if i want to print something in a textBox from my callback
function how can i access to my textBox ?  This->textBox1.Text or
Form1->textBox1.Text are not available in the callback

In other word i'm trying the print the handle or the caption of each
window in a TextBox control and i dont know how to access to my
TextBox from the callback (EnumWindowsProc).

In a console application I can just output (cout) each window handle
to the console but I cant figure out how to do this in a C++ form
project.  Is anybody know how to access to my TextBox1 from the
callback?

Thanks again!
David Wilkinson - 16 Sep 2007 12:27 GMT
> I'm wondering one another thing about CALLBACK functions....
>
[quoted text clipped - 10 lines]
> project.  Is anybody know how to access to my TextBox1 from the
> callback?

SQACPP:

I'm not so sure about managed/unmanaged issues, but in Win32 you would
pass a pointer to a user-defined struct as the LPARAM parameter of
EnumWindows(). This struct can contain anything you like (strings,
window handles, whatever).

Signature

David Wilkinson
Visual C++ MVP

SQACPP - 17 Sep 2007 05:44 GMT
> > I'm wondering one another thing about CALLBACK functions....
>
[quoted text clipped - 21 lines]
> David Wilkinson
> Visual C++ MVP

Sounds like a good ideas but i dont know how to declare the type of
"this" (Form1) to pass it to my callback function :

struct FormReference {
   int FormRef;    // ** What is the "this" (form1) type?
   int blabla;
};

BOOL CALLBACK MyEnumWindowsProc(HWND hwnd, LPARAM lparam)
{
  //  I want to access to this->textBox1->Text in this callback
function
  lparam.FormRef->textBox1->Text+="x\n";    // ?????
  return (TRUE);
}
//...
...main()
{
  FormReference *MyFormReference;
  // *** How to define define MyFormReference.FormRef=this; ?????????
  EnumWindows((WNDENUMPROC)MyEnumWindowsProc,0);    // ** How to pass
the pointer to the structure as LPARAM for the last parameter?
}
Ben Voigt [C++ MVP] - 17 Sep 2007 20:10 GMT
> On Sep 16, 2:06 am, "Jochen Kalmbach [MVP]" <nospam-
> Jochen.Kalmb...@holzma.de> wrote:
[quoted text clipped - 29 lines]
> project.  Is anybody know how to access to my TextBox1 from the
> callback?

Make your callback function an instance member of the Form.  Take off the
CALLBACK designator.  Together, this will make your callback function in
managed code.  Define a delegate type matching the EnumWindowsProc (the C#
version on pinvoke.net might be useful for comparison).  Use the
Marshal::GetFunctionPointerForDelegate method to have .NET compile the
native shim which contains the hidden "this" handle, and pass the resulting
pointer to EnumWindows (properly cast).  Now you can access any of the other
controls and members of your form from inside the callback.

As a side effect, you can again use /clr:pure.

> Thanks again!
SQACPP - 18 Sep 2007 06:48 GMT
> > On Sep 16, 2:06 am, "Jochen Kalmbach [MVP]" <nospam-
> > Jochen.Kalmb...@holzma.de> wrote:
[quoted text clipped - 46 lines]
>
> - Show quoted text -

Afters hours of trying to make the callback function as described I
restart from scratch with a working example found at  :
http://www.codeproject.com/managedcpp/cbwijw.asp   The only problem is
that this example use /oldSyntax and I manage to convert it to the new
syntax.  I'm still trying to figure out how to solve 2 errors and 1
warning.

Original /old syntax source : http://www.codeproject.com/managedcpp/cbwijw.asp

Here is the converted example :
======================
<Code>

#include "stdafx.h"
#using <mscorlib.dll>
#using <System.dll>
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>
#include <tchar.h>
#include <windows.h>

using namespace System;
using namespace System::ComponentModel;
using namespace System::Drawing;
using namespace System::Windows::Forms;

ref class CEnumWindows
{
private:
    __nogc class _CEnumWindows   //  **** Error C4980: '__nogc' : use of
this keyword requires /clr:oldSyntax ***
    {
    private:
        static  BOOL EnumWindowsProc(HWND hwnd, LPARAM)
        {
            CEnumWindows^ pew = CEnumWindows::GetClass();
            pew->m_EnumProc->Invoke(hwnd, NULL);   //*** Error C2664:
'CEnumWindows::EnumProc::Invoke' : cannot convert parameter 1 from
'HWND' to 'System::IntPtr'
            return TRUE;
        }
    public:
        void StartFinding()
        {
            EnumWindows((WNDENUMPROC)_CEnumWindows::EnumWindowsProc,NULL);
        }
    };
private:
    _CEnumWindows* m_ew;
public:
    delegate bool EnumProc(IntPtr hwnd, IntPtr lParam);
    static CEnumWindows^ GetClass()
    {
        return m_pclass;
    }
    static CEnumWindows^ m_pclass=NULL;
    CEnumWindows()
    {
        m_pclass = this;
        m_ew = new _CEnumWindows();
    }
    ~CEnumWindows()
    {
        delete m_ew;
    }
    void StartFinding()
    {
        m_ew->StartFinding();
    }
    EnumProc^ m_EnumProc;
};

public ref class NForm : public Form
{
public:
    bool EWHandler(IntPtr hwnd, IntPtr lParam)
    {
        char buff[512];
        if(GetWindowText((HWND)hwnd.ToInt32(),buff,511))
        {
            String^ s = String::Format("{0}{1}",
                hwnd.ToInt32().ToString("X8"),Convert::ToString(buff)); // ***
Warning    warning C4800: 'char *' : forcing value to bool 'true' or
'false' (performance warning) ***
            lbox->Items->Add(s);
        }
        return false;
    }
    NForm()
    {
        StartPosition = FormStartPosition::CenterScreen;
       Text = "Callbacks with IJW - Nish for CodeProject - Avoid
DllImport";
       Size = Drawing::Size(750,550);
       FormBorderStyle =
System::Windows::Forms::FormBorderStyle::FixedDialog;
        MaximizeBox = false;

        lbox = gcnew ListBox();
       lbox->Location=Point(5,5);
       lbox->Size=Drawing::Size(730,500);
        lbox->Sorted = true;

       Controls->Add(lbox);

        CEnumWindows^ p = gcnew CEnumWindows();
        p->m_EnumProc = gcnew
CEnumWindows::EnumProc(this,&NForm::EWHandler);
        p->StartFinding();

    }
    ListBox^ lbox;

};

int WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
    Application::Run(gcnew NForm());
   return 0;
}

</Code>

Here is the ***errors*** :
==================
Error C4980: '__nogc' : use of this keyword requires /clr:oldSyntax
  -> What is the new syntax for _nogc ? cant find much details on
google...
Error C2664: 'CEnumWindows::EnumProc::Invoke' : cannot convert
parameter 1 from 'HWND' to 'System::IntPtr'
  -> ????  no idea :(
Warning    warning C4800: 'char *' : forcing value to bool 'true' or
'false' (performance warning)
  -> ????  no idea :(

If i can find solution these errors I will be ble to integrate this
"example" in my C++ form project.

Thanks again for any clues on this issues...
Ben Voigt [C++ MVP] - 18 Sep 2007 14:14 GMT
>> > On Sep 16, 2:06 am, "Jochen Kalmbach [MVP]" <nospam-
>> > Jochen.Kalmb...@holzma.de> wrote:
[quoted text clipped - 59 lines]
> Original /old syntax source :
> http://www.codeproject.com/managedcpp/cbwijw.asp

I don't know that C++/CLI will even allow you to nest an unmanaged class
inside a ref class, in any case the new syntax for __nogc class is simply
"class", no "ref" or "value" prefix.

You could do what David suggested and pass the handle to your form through
the extra parameter provided for your use.  To do that, you will need your
original code and GCHandle::Alloc, GCHandle::Target, and GCHandle::Free.
The problem with passing a pointer through unmanaged code is that the
garbage collector might move your form around while running your callback,
then it will adjust the pointer that you received, but the next time the
callback is invoked, it will get the original pointer location which is no
longer valid.  GCHandle solves this problem.
SQACPP - 21 Sep 2007 21:57 GMT
> >> "SQACPP" <lsdiscip...@hotmail.com> wrote in message
>
[quoted text clipped - 78 lines]
>
> - Show quoted text -

Thanks for your help!

I'm still trying to make the enumwindows works and being able to
display the results of enumWindows in my form (this->listBox2->Items-
>Add(...)

using namespace System::Runtime::InteropServices;
BOOL CALLBACK MyEnumWindowsProc(HWND hwnd, LPARAM lparam)
{
   //GCHandle MyThis = GCHandle::FromIntPtr(lparam);    //** not
working since LPARAM is not a IntPtr
   //Form MyForm= gcnew System::Windows::Forms::;    // ** Dont know
how to define a new "this" instance (my form)

  // GCHandle gch = GCHandle.FromIntPtr(param);
  // TextWriter tw = (TextWriter)gch.Target;
  // tw.WriteLine(handle);
return (TRUE);
}

// ....

GCHandle gch = GCHandle::Alloc(this);
// *** NOT WORKING :
EnumWindows(MyEnumWindowsProc,GCHandle::ToIntPtr(gch));  //** not
working since LPARAM is not a IntPtr
EnumWindows(MyEnumWindowsProc,0);
// ....

I need help to understand how to change the lparam param to a IntPtr
without having compiling errors like :

[error C4439: 'AutomationWinForm::MyEnumWindowsProc' : function
definition with a managed type in the signature must have a __clrcall
calling convention]

when i change my the last param of my callback like this : BOOL
CALLBACK MyEnumWindowsProc(HWND hwnd, IntPtr lparam)

and

[error C2664: 'EnumWindows' : cannot convert parameter 1 from 'BOOL
(__stdcall *)(HWND,System::IntPtr)' to 'WNDENUMPROC'    ]

when I change the call to enumWindows like this
EnumWindows(MyEnumWindowsProc,GCHandle::ToIntPtr(gch));

Also it still not clear how to define a new instance of my form
(this) :

Really need help!...thanks!
SQACPP - 23 Sep 2007 08:14 GMT
> > "SQACPP" <lsdiscip...@hotmail.com> wrote in message
>
[quoted text clipped - 138 lines]
>
> - Show quoted text -

Any idea?
Ben Voigt [C++ MVP] - 25 Sep 2007 19:47 GMT
> I'm still trying to make the enumwindows works and being able to
> display the results of enumWindows in my form (this->listBox2->Items-
[quoted text clipped - 5 lines]
>    //GCHandle MyThis = GCHandle::FromIntPtr(lparam);    //** not
> working since LPARAM is not a IntPtr

There's a converting constructor, try GCHandle::FromIntPtr(IntPtr(lparam))
or else GCHandle::FromIntPtr(IntPtr((void*)lparam))

>    //Form MyForm= gcnew System::Windows::Forms::;    // ** Dont know
> how to define a new "this" instance (my form)
[quoted text clipped - 11 lines]
> EnumWindows(MyEnumWindowsProc,GCHandle::ToIntPtr(gch));  //** not
> working since LPARAM is not a IntPtr

use GCHandle::ToIntPtr(gch).ToPointer()

> EnumWindows(MyEnumWindowsProc,0);
> // ....
[quoted text clipped - 21 lines]
>
> Really need help!...thanks!
SQACPP - 30 Sep 2007 09:06 GMT
> > I'm still trying to make the enumwindows works and being able to
> > display the results of enumWindows in my form (this->listBox2->Items-
[quoted text clipped - 54 lines]
>
> - Show quoted text -

Thanks for still trying to help me!....

BOOL CALLBACK MyEnumWindowsProc(HWND hwnd, LPARAM lparam)
{
       GCHandle MyThis = GCHandle::FromIntPtr(IntPtr(lparam)) ;
       // ** missing code here to be able to access to my form **//
        MyThis->Label1->Text="blabla";
        return (TRUE);
}

// ....

GCHandle gch = GCHandle::Alloc(this);
EnumWindows(MyEnumWindowsProc,GCHandle::ToIntPtr(gch).ToPointer());   //
** Error **//

This code return the error Error C2664: 'EnumWindows' : cannot convert
parameter 2 from 'void *' to 'LPARAM'

instead of printing "blabla" in the label1 of my form each time the
callback proc is called for each windows.

I have no clues about how to recreate a usable form "instance" in my
callback procedure... The following code in the proc is to output to
the console but how to work with a form instead ???
    GCHandle gch = GCHandle.FromIntPtr(lparam);
    TextWriter tw = (TextWriter)gch.Target;
     tw.WriteLine(handle);

Thanks...

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.