Embedding windows in SalesLogix

Something that I do quite often, and have done since early versions of SalesLogix is embed my own applications into the running Sales Client. I recently posted to my main blog about some tips to get started doing this from C#. It really is easy to do.

I recently built an application for SalesLogix that monitors for exceptions on opportunities (An exception being something defined by an administrator for something such as no activities on an opportunity that has a status of open). Anyway, I needed the app to be able to notify users when they move to an opportunity (or it’s associated contact or account) that had an exception. Some kind of visual alert. However, I wanted to be able to install this without the need to modify any existing screens like the Account, Contact, or Opportunity detail screens (Reason being that it makes it difficult for upgrades and also then you have to build it into the existing customizations on those screens). So, I decided to take the approach to embed something in the top black strip in the Sales Client. For this app I too a button and embedded that – then the user could also click that to bring up a window that detailed the exceptions present on the current record. Here’s a sample:

Click for larger picture

What you’re seeing there is a .NET Button object embedded into an uncustomizable area in SalesLogix. Pretty cool. So, how do I do that? Easy. First of all, read the post from my main blog I mentioned before. That will get you a little up to speed on some of it. The remaining part not mentioned in my other post is the use of the SetParent Win32API. SetParent allows you to to the handle of a windowed object and assign the handle of a new parent window. It is my favorite API – but that is another blog entry.

First, you need to discover the running Sales Client and then find the handle of the TPanel object that we’ll be embedding the button into. As outlined in my other post, you have two ways to do that. However, since we need to be able to also find a child handle for the TPanel object we’ll use the FindWindow approach along with the FindWindowEx Win32API to drill down from the main SalesLogix window handle, to the child to the MDI client container handle, then to the main view window, and finally to the TPanel where we’ll embed the button. Let’s get started into the code. I’ve omitted the DllImports for the API calls for brevity – you can download the full code at the end of this post.

//Find SalesLogix app main window handle
IntPtr hwnd = FindWindow("TmdiMain", null);
if (!hwnd.Equals(IntPtr.Zero))
    //Find MDI client container handle
    hwnd = FindWindowEx(hwnd, IntPtr.Zero, "MDIClient", null);

    //Find main view handle
    if (!hwnd.Equals(IntPtr.Zero)) hwnd = FindWindowEx(hwnd, IntPtr.Zero, "TfrmNewMainView", null);

    //find TPanel handle
    if (!hwnd.Equals(IntPtr.Zero)) hwnd = FindWindowEx(hwnd, IntPtr.Zero, "TPanel", null);

    //Now we'll embed the button
    if (!hwnd.Equals(IntPtr.Zero))
        SetParent(button1.Handle, hwnd);
        //Now we need to reposition the button in the TPanel otherwise
        //we won't see it because it is to low at the moment.
        //To do this we need to get the RECT of the TPanel object and
        //then reposition the button according to those coordinates

        Rect rect = new Rect();
        GetWindowRect(hwnd, ref rect);
        button1.Location = new Point((int)(rect.Width/2)-(int)(button1.Size.Width/2), 3);

So the end result looks like this:

Not bad. Now to remove the button, or unembed it, all we have to do is set the parent back to the original handle. When you can SetParent, it returns an IntPtr which is the original handle. You can use that, or set it back to the handle of the form it came from.

Update: By request, I’ve added the sample code in VB.NET also – which was painful for me since I am not a fan of VB 😉  -Enjoy.

Download a sample project containing the code here (C#)
Download a sample project containing the code here (VB.NET)

Edit: A change in SalesLogix 6.2 was that the MainView container window (inside MDIClient) is now named “TfrmNewMainView” insetad of it’s previous object “TwndMainView2”. I updated the code in this post, but you’ll need to change the download to match.


Ryan Farley

Ryan Farley is the Director of Development for Customer FX and creator of slxdeveloper.com. He's been blogging regularly about SalesLogix, now Infor CRM, since 2001 and believes in sharing with the community. His new passion for CRM is Creatio, formerly bpm'online. He loves C#, Javascript, web development, open source, and Linux. He also loves his hobby as an amateur filmmaker.

1 Comment

  1. Cheers Ryan, works a treat.


Submit a Comment

Your email address will not be published. Required fields are marked *

Subscribe To Our Newsletter

Join our mailing list to receive the latest Infor CRM (Saleslogix) and Creatio (bpm'online) news and product updates!

You have Successfully Subscribed!