Wednesday, December 14, 2005

Ever wondered how exactly ASP.NET goes about combining the code-behind files (*.cs/*.vb) with page files (*.aspx) and creates DLLs that somehow run as a website?  Here's your answer:
http://msdn.microsoft.com/msdnmag/issues/06/01/ExtremeASPNET/

Wednesday, December 14, 2005 6:07:49 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Tuesday, December 13, 2005

I've seen a lot of questions about implementing KB196340 in managed code as well as getting an IWebBrowser2 interface from an IHTMLDocument2 or IHTMLWindow2 interface.  I had the same questions, so I dug in and below is what I came up with.  I have yet to have any problems with it, but it may need some work with releasing the COM objects (feel free to comment if you have suggestions.)


IEnumUnknown

[

ComImport,

Guid("00000100-0000-0000-C000-000000000046"),

InterfaceType(ComInterfaceType.InterfaceIsIUnknown)

]

public interface IEnumUnknown

{

    [PreserveSig]

    int Next(

        [In, MarshalAs(UnmanagedType.U4)] int celt,

        [Out, MarshalAs(UnmanagedType.IUnknown)] out object rgelt,

        [Out, MarshalAs(UnmanagedType.U4)] out int pceltFetched

    );

 

    [PreserveSig]

    int Skip(

        [In, MarshalAs(UnmanagedType.U4)] int celt

    );

 

    void Reset();

 

    void Clone(

        out IEnumUnknown ppenum

    );

}

 


IOleContainer

[Flags()]

public enum tagOLECONTF

{

    OLECONTF_EMBEDDINGS = 1,

    OLECONTF_LINKS = 2,

    OLECONTF_OTHERS = 4,

    OLECONTF_ONLYUSER = 8,

    OLECONTF_ONLYIFRUNNING = 16,

}

 

[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("0000011B-0000-0000-C000-000000000046")]

public interface IOleContainer

{

    [PreserveSig]

    int ParseDisplayName(

        [In, MarshalAs(UnmanagedType.Interface)] object pbc,

        [In, MarshalAs(UnmanagedType.BStr)] string pszDisplayName,

        [Out, MarshalAs(UnmanagedType.LPArray)] int[] pchEaten,

        [Out, MarshalAs(UnmanagedType.LPArray)] object[] ppmkOut

    );

 

    [PreserveSig]

    int EnumObjects(

        [In, MarshalAs(UnmanagedType.U4)] tagOLECONTF grfFlags,

        out IEnumUnknown ppenum

    );

 

    [PreserveSig]

    int LockContainer(

        bool fLock

    );

}


GetBrowserFromWindow (added method to the WebBrowserEx control)

public IWebBrowser2 GetBrowserFromWindow(IHTMLWindow2 win)

{

  if(win == null)

  {

    throw new ArgumentNullException("win");

  }

 

  IWebBrowser2 result = null;

 

  //if the document is the top level document, we don't have to look for it

  if(win.document == this.CurrentDocument)

  {

    result = this.IWebBrowser2; //internal reference to the top-level IWebBrowser2

  }

  else

  {

    //get the OLE container from the window's parent

    IOleContainer oc = win.parent.document as IOleContainer;      //OC ALLOC

 

    //get the OLE enumerator for the embedded objects

    int hr = 0;

    IEnumUnknown eu;

    hr = oc.EnumObjects(tagOLECONTF.OLECONTF_EMBEDDINGS, out eu); //EU ALLOC

    Marshal.ReleaseComObject(oc);                                 //OC FREE

    Marshal.ThrowExceptionForHR(hr);

 

    Guid IID_IWebBrowser2 = typeof(SHDocVw.IWebBrowser2).GUID;

    object pUnk = null;

    int fetched = 0;

    const int MAX_FETCH_COUNT = 1;

 

    //get the first embedded object

    hr = eu.Next(MAX_FETCH_COUNT, out pUnk, out fetched);         //PUNK ALLOC

    Marshal.ThrowExceptionForHR(hr);

 

    //while sucessfully get a new embedding, continue

    for(int i = 0; HRESULTS.S_OK == hr; i++)

    {

      //QI pUnk for the IWebBrowser2 interface

      SHDocVw.IWebBrowser2 brow = pUnk as SHDocVw.IWebBrowser2;

 

      if(brow != null)

      {

        //if the document for this browser matches the one passed in, we found it

        if(brow.Document == win.document)

        {

          result = brow;

          break;

        }

        else

        {

          Marshal.ReleaseComObject(brow);                         //PUNK FREE

        }

 

      } //if(brow != null)

 

      //get the next ebmedded object

      hr = eu.Next(MAX_FETCH_COUNT, out pUnk, out fetched);       //PUNK ALLOC

      Marshal.ThrowExceptionForHR(hr);

 

    } //for(int i = 0; HRESULTS.S_OK == hr; i++)

 

    Marshal.ReleaseComObject(eu);                                 //EU FREE

  }

 

  return result;

}

Wednesday, December 14, 2005 4:14:38 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Wednesday, December 07, 2005
I ran across this code today.  This would be a good example of how NOT to dispose a dialog form.  It seems that "someone" though it would be a good idea to dispose the form only when an exception occurred?!?  Genius.  Unfortunately, I was the genius.  I should really watch my caffeine consumption!  Oh well, it's good to laugh at your own "creativity" once in a while... right? :-P

Dim frm As MyForm

Try
   frm = New MyForm
   With frm
      .StartPosition = FormStartPosition.CenterParent
      .Width = 650
      .Height = 600
      .ShowDialog()
   End With

Catch ex As Exception 'this should "probably" be "finally"
   If Not frm Is Nothing Then
      frm.Dispose()
   End If

End Try
Wednesday, December 07, 2005 11:48:13 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 

Ken McNamee has been thinking outside the SQL box.  I didn't realize that you can use a "case" statement in the "order by" clause:


DECLARE @orderBy varchar(50)
SET @orderBy = 'LastName'

SELECT
    *
FROM
    Employees
ORDER BY
    CASE
        WHEN @orderBy = 'LastName' THEN LastName
    END,
    CASE
        WHEN @orderBy = 'HireDate' THEN HireDate
    END

For more on this, see his post:
http://blogs.vertigosoftware.com/kenm/archive/2005/12/06/Dynamic_ORDER_BY_Clause.aspx

Wednesday, December 07, 2005 3:58:29 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  | 
 Monday, December 05, 2005

Jeff Atwood recently posted a list of windows tips and tricks on his blog.  The list included using Ctrl+C to copy the text out of message boxes.  This trick has been invaluable to me for a while, especially in place of "can you send me a screen shot of that?" 

But here's the kicker: Who knew that you could Ctrl-Click the taskbar to select multiple items and then perform actions (e.g. cascade,tile,close) on your selection?  Where have I been?  Jeff, you're the man.

Tuesday, December 06, 2005 6:52:48 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [2]  |