Interop question

  • Thread starter Thread starter michelqa
  • Start date Start date
M

michelqa

When executing some win32 messages in c# I get unexpected results.
The following example is suppose to return the handle of an image in a
button control of another application but it return a negative
handle...is anybody know why it return an invalid handle like
"-989523277" ??

IntPtr ImageHandle =
Win32.SendMessage(Handle,BM_GETIMAGE,IntPtr.Zero,IntPtr.Zero);
MessageBox.Show(ImageHandle.ToString());

Note : the third param is set to IMAGE_BITMAP (0); it return 0 if
the button contain no image.

Thanks...
 
Can you be more specific?  Why do you believe the value "-989523277" tobe  
an invalid handle value?  Have you actually tried to use it as an HBITMAP  
and had that fail?  Can you show a concise-but-complete code sample that  
reliably demonstrates whatever problem you're actually having?

Pete

I suppose it's invalid since it's negative and since i'm not able to
recreate the bitmap in my application...it return a "Generic
exception"

//Handle = button handle of another application
IntPtr ImageHandle =
Win32.SendMessage(Handle,BM_GETIMAGE,IntPtr.Zero,IntPtr.Zero);
MessageBox.Show(ImageHandle.ToString());
System.Drawing.Bitmap Bitmap =
System.Drawing.Bitmap.FromHbitmap(ImageHandle); //generic exception
from gdi..invalid handle?
// Just want to get a usable bitmap here
 
Ok , I'll try to explain the problem :
1- I know that WM_GETIMAGE is suppose to return an hImage hex
c50512b3 (3305444019) ... I know that because I'm logging the message
in SPY++
2- My sendMessage in my c# app return -989523277 (or
8975925797277995699 when modifying sendmessage definition to return a
long instead of a IntPtr) *** Why this difference???? ****
3- Even with the correct image handle hardcoded like this :
System.Drawing.Image MyImg=
System.Drawing.Image.FromHbitmap((IntPtr)3305444019);
I get the error : Arithmetic operation resulted in an overflow.

As I understand it FromHbitmap want an IntPtr and 3305444019 is to big
for a Integer

Dont think a more complete example will help to understand the problem
but here is my example...I have a Win32 application and I want to copy
Button image from it and put the image in a button or a picturebox in
my c#

[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hwnd, int msg, IntPtr
wparam, IntPtr lparam);
int BM_GETIMAGE = 0x00F6;
IntPtr ImageHandle =
SendMessage(Handle,BM_GETIMAGE,IntPtr.Zero,IntPtr.Zero);
MessageBox.Show(ImageHandle.ToString());
System.Drawing.Image MyImg=
System.Drawing.Image.FromHbitmap((IntPtr)3305444019); //Arithmetic
operation resulted in an overflow.
//System.Drawing.Image MyImg=
System.Drawing.Image.FromHbitmap(ImageHandle); //Exception
Button Button1 = new Button();
Button1.Image=MyImg;
 
Just to make things correctly :

1- Download controlSpy from
http://www.microsoft.com/downloads/...4d-0531-4ec2-8b27-2e463b315f16&displaylang=en
2- Run controlSpy6.exe. Go to the button section, Apply the BS_BITMAP
style, and then go to the Message tab and send the "SetImage" message.
3- With Spy++ get the handle of the button and convert it to integer
4- Replace the Handle value in for the Handle variable in the
Form_load of the following code
5- Run the code. (My code is .net 1.0)
<Code>
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Data;

namespace GetWin32ButtonImage
{
public class Form1 : System.Windows.Forms.Form
{
private System.ComponentModel.Container components = null;

public Form1()
{
InitializeComponent();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code

private void InitializeComponent()
{

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);

}
#endregion

[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hwnd, int msg,
IntPtr
wparam, IntPtr lparam);

[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void Form1_Load(object sender, System.EventArgs e)
{
IntPtr Handle=(IntPtr)666666; //*** REPLACE THE HANDLE HERE ***//
int BM_GETIMAGE = 246;
IntPtr ImageHandle =
SendMessage(Handle,BM_GETIMAGE,IntPtr.Zero,IntPtr.Zero);
System.Drawing.Image MyImg=
System.Drawing.Image.FromHbitmap(ImageHandle);
MessageBox.Show("We have a valid bitmap!!! :
height="+MyImg.Height.ToString())
}
}
}
</Code>

Now we have a full working example! ;o) You can skip the 3 first step
if you can find a button with BS_BITMAP style and with an image. (not
an icon...BS_ICON)
 
The ImageHandle you are retrieving is relative to the button's process. In
the process in which you are trying to create the Bitmap that handle is
meaningless.
 
OK thanks....that's explain the weird unusable image handle... The
*only* way to do it will be by creating and a dll to inject into the
other process and setting a windows hook. Is there any other way to
execute my code into the other process ?
 
It's _possible_ that if you describe what you're really trying to do here,  
 from the high-level goal perspective, ignoring completely any particular  
implementation details, someone could offer better advice.

Pete

I'm doing a tool like spy++. Win32 controls are interpreted (runtime
converted) as .net object
for example Win32 control properties are displayed in a managed
propertyGrid of my spy++ application just like any other .Net
control.

My question was about filling Button.Image in my property grid
(selectedObject is a button) when converting a Win32 control to a .net
control.

I was just wondering why WM_GETIMAGE return unusable image handle...
(never seen a negative handle since now) With your help I understand
that it return a negative unasable handle because it's in another
process.

I already use a dll and a windows hook to get things like
Button.ImageList with WM_GETIMAGELIST and will probably use the same
kind of code to get the image handle of WM_GETIMAGE from the other
process.

Pete : What you mean By malware-like techniques?? Is there any other
way to do this without hooking windows to inject a dll into the other
process???

Since you always trying to help me in different threads here , you now
know why i'm asking win32 to .net questions. :)
 
Back
Top