7 Replies - 158 Views - Last Post: 30 June 2020 - 04:26 PM Rate Topic: -----

#1 GIS-Monkey   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 30-June 20

API Question - Acquiring reference to Rect from SendMessage

Posted 30 June 2020 - 11:26 AM

Greetings,

I ran into a thread on the VB.NET forum that was helpful, but I got stuck when I tried to apply their API 'hack' solution to their problem.

Here's my problem... I have a bound combobox control that's linked to a list of file paths. I want to perform a live reformat of those paths to fit them in the combobox text and dropdown displays (e.g. to something like "D:/.../<filename>"). The convenience is since the dialog is resizable, if there happens to be enough space, I'd like to display the full path. I'm running into the same problem the original author of the linked thread encountered - i.e. the modified entries in the dropdown won't refresh without a mouseover action. I'd like to implement the 'listbox hack' solution recommended by IronRazor, but my PInvoke/API skills are still pretty rough (and in this case I am operating in c#). The essence of his hack was to substitute a listbox control for the dropdown of the combobox and to hijack the dropdown action to display the listbox on top of the dropdown display. The listbox control supposedly provides more responsiveness to being refreshed so that's why it's the path for this solution. A key part of his recommendation was the following...

Quote

View PostIronRazer, on 03 May 2016 - 12:07 PM, said:

There is a method that you can use to get the DropDown rectangle of the ComboBox using the CB_GETDROPPEDCONTROLRECT message with the SendMessage Api function so that you can set the bounds of the ListBox to the same rectangle location and size before making it visible.


Now, I think I have the API implementation in place, but I can't quite acquire the reference to the dropdown rectangle from the lParam reference pointer of the SendMessage function. The problem seems to be converting from a pointer to an object reference. I feel that I'm so close but so far away. I know 'GCHandle' probably isn't the solution, but I haven't seen an other alternative strategies. Any recommendations on moving forward here would be hugely appreciated!

using System;
using System.Runtime.InteropServices;

public partial class MyForm : System.Windows.Forms.Form
{

        [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        private static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, ref int lParam);

        private void cboPath_Workspace_DropDown(object sender, EventArgs e)
        {
            int lParam = 0;
            var iReturn = SendMessage(this.cboPath_Workspace.Handle, CB_GETDROPPEDCONTROLRECT, 0, ref lParam);
            var pPointer = (IntPtr)lParam;
            var pObject = GCHandle.FromIntPtr(pPointer); // I know this is wrong; and it blows up here in any case with a FatalExecutionEngineError
            var pRect_DropDownBounds = (Rectangle)pObject.Target;
            this.lstPath_Workspace.Size = new Size(pRect_DropDownBounds.Width, pRect_DropDownBounds.Height);
            this.lstPath_Workspace.Visible = true;

        }
}



Is This A Good Question/Topic? 0
  • +

Replies To: API Question - Acquiring reference to Rect from SendMessage

#2 Skydiver   User is online

  • Code herder
  • member icon

Reputation: 7404
  • View blog
  • Posts: 24,977
  • Joined: 05-May 12

Re: API Question - Acquiring reference to Rect from SendMessage

Posted 30 June 2020 - 12:00 PM

You need to pass a pointer to a RECT structure for the message to fill in. It's not a matter of the message coming back and returning a pointer to a rectangle.
Was This Post Helpful? 0
  • +
  • -

#3 GIS-Monkey   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 30-June 20

Re: API Question - Acquiring reference to Rect from SendMessage

Posted 30 June 2020 - 12:12 PM

SEE!!!??? I totally knew it was something headslappingly simple that I was missing. That was the ticket, thank you.
Was This Post Helpful? 0
  • +
  • -

#4 GIS-Monkey   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 30-June 20

Re: API Question - Acquiring reference to Rect from SendMessage

Posted 30 June 2020 - 12:18 PM

Except.... now the return rectangle doesn't seem to match up with my combobox dropdown in terms of size. Do I need to do some type of conversion, or am I referencing the wrong windows handle in SendMessage?

        private void cboPath_Workspace_DropDown(object sender, EventArgs e)
        {
            var pRect_Bounds = new Rectangle();
            var iReturn = SendMessage(this.cboPath_Workspace.Handle, CB_GETDROPPEDCONTROLRECT, 0, ref pRect_Bounds);
            this.lstPath_Workspace.Size = new Size(pRect_Bounds.Width, pRect_Bounds.Height);
            this.lstPath_Workspace.Visible = true;

        }



Here: pRect_Bounds indicates the following properties --> (Height:213; Width:1044)
My combobox control has a width of 295. My form has a width of 662.

What else am I missing here?
Was This Post Helpful? 0
  • +
  • -

#5 Skydiver   User is online

  • Code herder
  • member icon

Reputation: 7404
  • View blog
  • Posts: 24,977
  • Joined: 05-May 12

Re: API Question - Acquiring reference to Rect from SendMessage

Posted 30 June 2020 - 01:04 PM

You need to marshal the rectangle from the managed side to the unmanaged side and back again.

Here's some approaches:
Let the compiler do the work:
[StructLayout(LayoutKind.Explicit)]  
public struct RECT {  
    [FieldOffset(0)] public int left;  
    [FieldOffset(4)] public int top;  
    [FieldOffset(8)] public int right;  
    [FieldOffset(12)] public int bottom;  
}

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, ref RECT lParam);

:

var rect = new RECT();
SendMessage(hwnd, CB_GETDROPPEDCONTROLRECT, 0, ref rect);



Do the marshaling yourself:
[StructLayout(LayoutKind.Explicit)]  
public struct RECT {  
    [FieldOffset(0)] public int left;  
    [FieldOffset(4)] public int top;  
    [FieldOffset(8)] public int right;  
    [FieldOffset(12)] public int bottom;  
}

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);

:

IntPtr rectBuffer = Marshal.AllocCoTaskMem(Marsal.SizeOf(typeof(RECT)));
SendMessage(hwnd, CB_GETDROPPEDCONTROLRECT, 0, rectPointer);
RECT rect = Marshal.PtrToStruct<RECT>(rectBuffer);
Marshal.FreeCoTaskMem(rectBuffer);



All code above untested. Just trying to recall most of the stuff and doing quick lookups in docs.microsoft.com.
Was This Post Helpful? 0
  • +
  • -

#6 GIS-Monkey   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 30-June 20

Re: API Question - Acquiring reference to Rect from SendMessage

Posted 30 June 2020 - 01:52 PM

Aha... ok that looks like the secret handshake I was looking for. Thank you. I'll give this a shot and see how it goes.
Was This Post Helpful? 0
  • +
  • -

#7 GIS-Monkey   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 30-June 20

Re: API Question - Acquiring reference to Rect from SendMessage

Posted 30 June 2020 - 02:22 PM

Ok, I got the RECT struct correctly, it looks like, but I must be passing in the wrong windows handle. this.cboPath_Workspace.Handle causes the return RECT to be the size of the combobox, not the dropdown (which is what I'm aiming for). Any suggestions there?
Was This Post Helpful? 0
  • +
  • -

#8 Skydiver   User is online

  • Code herder
  • member icon

Reputation: 7404
  • View blog
  • Posts: 24,977
  • Joined: 05-May 12

Re: API Question - Acquiring reference to Rect from SendMessage

Posted 30 June 2020 - 04:26 PM

Well the documentation did say it would return the entire combobox:

Quote

An application sends a CB_GETDROPPEDCONTROLRECT message to retrieve the screen coordinates of a combo box in its dropped-down state.


Perhaps this would be better: CB_GETDROPPEDWIDTH
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1