The Code Project Click here for Dundas Software's TCP/IP Development Kit
Home >> Dialog and Windows Programming >> Unedited Reader Contributions

SlickSkins™... Give Your Browser A New Shape!
By Bill SerGio

Create Very Cool GUIs by Reshaping Internet Explorer 
 VC 4-6, Win95-98, NT4, W2K, MFC, ATL, STL
 Posted 28 Jan 2001
 Updated 1 Feb 2001
Articles by this author
Send to a friend
Printer friendly version
[This is an unedited reader contribution] [Modify this article] [Delete this article]
Home Lounge New Articles Logon Forums Contribute
Broken links? Email us!
393 users have rated this article. result:
4.44 out of 5.

  • Download demo project - 605 Kb
  • Sample Image - screenshot.gif

    Introduction


    Bill SerGio is a CTO, Project Leader, Architect, and  Programmer  Visual C++ and Java.
    He specializes in GUI, 3D-Scaled Vector Graphics, Animation, Streaming Video, and DirectX.
    And, LARGE Scale Databases & Servers, Winsock, Peer-to-Peer for Business, and WAP(Pocket PC).

    Download Sample

    What's the big deal with skins anyway? 

    In addition to looking very cool, they provide many programming advantages in the development of all kinds of business applications.  Early examples of skins simply painted the frame of a window to make it more visually interesting, then someone added the concept of a non-rectangular shape to the window itself.   And back in 1997, I decided to add one more component to skins, a powerful SDK interface, namely the Internet Explorer browser. 

    Consider all of the incredible functionality built into the Internet Explorer browser(which is really just "shadocvw.dll") like DHTML, Java, Video, and the ease of creating fantastic looking web pages which can reside client side or come from a remote server.  All we need to is to DISGUISE the Internet Explorer browser so we can use all of the incredible GUI functionality that is ALREADY resident in "shadocvw.dll" resident on every Windows platform.

    Just think of the development time companies can save in creating and updating their applications GUI screens because instead of hiring a  C++ programmer, they can have their artist change any program screen and its functionality remotely or client side in just seconds! And any screen can be displayed in any language, including Japaneese and Chinese instantly without increasing the size of the executable file, and without the need for any additional programming.

    Disguising Internet Explorer

    It's easy to disguise Internet Explorer so its looks exactly like any other screen you would create in Visual C++ by simply creating a non-rectangular, region, or skin.

    The sample code with this article can make it easy to create and install in just a FEW DAYS a "software package" that consists of a shopping cart, a JRun sever or Apache server on the company's website connected to an Oracle database, SQL database, or Visual FoxPro database that can handle millions of hits per hour, and that includes a client side Visual C++ or Java application of 300kb or less that includes hundreds of spectacular GUI screens with ANY custom functionality that can be instantly displayed in ANY language including Japanese and Chinese on the user's computer. 

    The idea behind using these "Browser Skins" is to set up a company's website using JSP or ASP, with a "Skins" application in Visual C++ or pure Java where each screen in the application was the Internet Explorer WebBrowser Control (i.e., "Shdocvw.dll"). A company can then distribute this type of Skins software to millions of people to provide users with an application that "interfaces" in some way with their Internet Explorer and Netscape browsers. For example, one common use, for such "Skins" applications is to provide competitive pricing alternatives to users while they are shopping on some website. 

    It's easy to write "scraping" code that can reside either on the client side or server side to "scrap" any web page to provide an instant comparison between any product on that web page with a company's competitively priced similar products in a database. A JSP or ASP server can return the ACTUAL ENTIRE SCREEN and ITS REGION back to the Visual C++ or Java application running on the user's computer INSTANTLY in ANY language, including Japanese or Chinese. Screens could also be generated from the client side as well. 

    Browser Skins lets you create applications smaller than 300kb in size that can display an unlimted number of diferent screens in different shapes, with different functionality, in ANY language INSTANTLY!  Skin applications can be both client based and server based making it possible to instantly change any screen or its functionality on millions of computers without the necessity of the user downloading a new update. 

    This approach also serves to permanently link any company with millions of people's computer so that they can constantly advertise to their users. 

    Skins Are "Self-Distributing"

    Skins are by their very nature "self-distributing" which means that people like to play with them so much that skins of any kind are the hottest downloads on the Internet. Simply add  a Peer-to-Peer server class and some utility like a legal version of Napster, and you can find your skins application on millions of computers in just weeks! 

    And finally, any non-rectangular skinned Internet Explorer application that is both client and server based must sink the events of the user's browser to provide a truly interactive business application that responds to the user's Internet activity.  This article and sample code illustrate the following software techniques:

    • Skins editor to create skins & regions from ANY type of image: .gif, .jpg, .bmp, .avi, etc.
    • Dynamically create Microsoft's WebBrowser Control("Shdocvw.dll") in modeless skinned dialogs 
    • Sinking events correctly in Microsoft's WebBrowser Control("Shdocvw.dll")
    • Put Microsoft's WebBrowser Control("Shdocvw.dll") inside an AppBar, button or control
    • Dynamically create WebBrowser Control in an ATL or MFC or Video window in any application
    • Put WebBrowser Control in an ATL I.E. "Band" and dynamically change it from a server
    • Resize non-rectangular skin regions dynamically on any computer
    • Save regions to files & create regions from files
    • Create new GUI screens in any language INSTANTLY on millions of computers
    • Create sinks that get around some ISPs using an ATL window to prevent sinking I.E.
    • Many skin techniques & tricks never seen anywhere before 

    Application Pathway

    Most applications place the INSTALLATION PATHWAY in the registry when the user runs some installation program like InstallShield.  Since this is source code for Visual Studio, I assume that the user will run the programm either in Debug or Release Mode from WITHIN the IDE.  Therefore I placed the skins directory one level ABOVE the Release and Debug directories to what "GetCurrentDir" will return as the "executable" path from the IDE. If you were to double-click on the .exe file in the Debug or Release directories you will get a lot of errors and problems because the program will NOT be able to find skins directory. To run the application by double-clicking on an .exe, the skins directory MUST be in the SAME directory as the .exe file. If the "Skins" directory is NOT inside of the same directory that the application is running from, the application will prompt the user to select the "Skins" directory so it can set the correct pathway to "Skins" directory.

    Skinned Modeless Browser Dialogs

    I created a Skin Browser Class called "CSkinDlg" that creates modeless dialogs with a non-rectangular region and a dynamically created Microsoft WebBrowser Control. 

    By using modeless dialogs where the entire surface of the dialog is covered with a browser we have a GUI screen that is instantly language independent with incredible graphics and includes powerful XML functionality without the need to write any code!  In addition, the GUI content can be either client side based or server based which means that a company can INSTANTLY change all of the screens and their functionality in their software in less than one second on millions of computers without ever re-installing one copy of their software! 

    This means that ALL of the screens in this sample application are skinned, non-rectangular browser windows filled with .htm files which allows for spectacular looking screens that can be easily modified by anyone either client side or server side. 

    I have made millions of dollars from the sales of my custom skinned peer-to-peer software programs that I have written and the key factors in their sales was the "Skinned GUI."   Skins provide a lot more than simply a slick looking screen in that they drastically reduce the cost and development time of any application, and allow a company to provide information to installed applications on millions of computers instantly without using anymore bandwidth than a dial-up modem!  That is why "Skinned Server Based Business Applications" are so hot right now. 

    Skinned Modeless Application Bars

    I usually add a skinned Application Bar with a dynamically created WebBrowser Control to this apllication as well.  I left it out to try to make this sample easier to follow but I will either add it in a future update to this article, or post another separate article and project on creating a Skinned Application Bar, or "SkinBar" or "WebBar" as I call call them.

    The advantage to making the entire face of any application bar a web browser window is that anyone including an artist can completely change the look and functionality of the SkinBar remotely on millions of computers without the need of the user ever downloading and installing any update.

    Sample Wet Logo

    On the pop-up menu from the icon in the taskbar, you will see a menu choice entitled "Sample Wet Logo" which demonstrates several interesting effects.  You will notice that as you move your mouse over the logo "SerGio" you will get a nice water effect that is implemented with a Java applet but could just as easily been done with DHTML.  When you press the "More" link you will see how regions can be easily switched. And when you click on the close button in the upper-left hand corner of the skin you will see how to launch an instance of the Internet Explorer Browser through an interface instead of using "ShellExecute" which, in turn, through the Sink Library, will launch an animation in the Tray icon!

    If you click anywhere on the picture of my head, you will notice that the Internet Explorer GUI is "draggable" so that you can drag the ENTIRE skin browser window anywhere on the desktop. 

    The samples are simply meant to illustrate the incredible interfaces you can achieve easily by using Internet Explorer as your GUI in your C++, Visual C++, Visual Basic, and Visual FoxPro programs.

    I would have used a picture of a pretty model INSTEAD of my own head but I don't own the copyright to any pictures of models that I could use so I stuck in a picture of myself to illustrate the concept of "non-rectangular." 

    Creating Regions Dynamically

    There are a lot of different ways to setup the skin and its region. In this example, I have illustrated 2 of these ways:
  • Reading .htm and region file from a directory or zipped file that is located either on client or a server to create the skin. This allows you to create the region first while the browser is loading on a separate thread.
  • Reading .htm file from a directory or zipped file that is located either on client or a server, and then retrieving the region from the "OnDocumentComplete" event of the WebBrowser control. This technique means that the region can be read dynamically from an html tag that specifies the ".rgn" file or art file located on a remote server to use for the region and is better suited to some business applications.
  • For example, you could place the name of the region file, without the extension ".rgn," in the TITLE tag or any other tag and extract the region file name and/or the region data structure itself to be used to create the non-rectangular shape of the WebBrowser Control or CHtmlView from the OnDocumentComplete Event. 

    I included a number of methods for creating regions in this sample including:

    // Create region from region file(.rgn)

    BOOL File2Rgn(HWND hSkin, LPCSTR lpRgnPath);

    // Create region from DLL region resource

    BOOL Dll2Rgn(HWND hSkin, LPCSTR lpDLLFile);

    // Create region from a Resource file

    BOOL Res2Rgn(HWND hSkin, UINT nRegionID);

    // Create region from a Bimap(file or resource)

    BOOL Bmp2Rgn(HWND hSkin,HBITMAP hBmp,CString csRgnFile,COLORREF
    cTolerance);

    Saving Regions As Files
    The menu that pops up from the icon in the taskbar has a selection called "Region from Bitmap" that will create a region from a bitmap and save that region to a file with the same name, in the same directory as the bitmap but with the extension ".rgn" so you can create and save your own region files.

    Dynamic Re-Sizing of Regions
    I resize  the non-rectangular regions dynamically using using a STATIC DATA FILE for the region and "GetRgnBox(LPRECT lpRect )" to resize the region so that it fits every screen exactly on any monitor or operating system. 

    You can include a region file (.rgn) as you would a .gif or .jpg file art file and the program will retrieve the region file from any website as it would any image file since region files are only 3k or 4k in size and can reside either on the client computer or server side. 

    How To Make Internet Explorer GUI "Draggable"

    One important requirement is that we make our Internet Explorer GUI "draggable" so that users can click on some image, region or text INSIDE OF the displayed web page and, holding down their mouse, drag the ENTIRE browser window anywhere on the desktop. There are several ways to do this but the easiestr and most reliable I've found so far is the following:
    // Use OnBeforeNavigae2 to trap the mousedown event
    // We check URL for: "EVENT:csAction:csData:csQuestionMark"
    void CSkinDlg::OnBeforeNavigate2(LPDISPATCH pDisp,
                                                       VARIANT FAR* URL,
                                                       VARIANT FAR* Flags,
                                                       VARIANT FAR* TargetFrameName, 
                                                       VARIANT FAR* PostData,
                                                       VARIANT FAR* Headers,
                                                       BOOL FAR* Cancel) 
    {
            // Retrieve data as a string from a POST
            if (PostData != NULL && PostData->vt == (VT_VARIANT|VT_BYREF) && 
                    PostData->pvarVal->vt != VT_EMPTY ){
                    *Cancel = TRUE;
                    char *szTemp = NULL, *szPostData = NULL;
                    long plLbound, plUbound;

                    SAFEARRAY *parrTemp = PostData -> pvarVal->parray;
                    SafeArrayAccessData(parrTemp , (void HUGEP **) &szTemp);

                    SafeArrayGetLBound(parrTemp , 1, &plLbound);
                    SafeArrayGetUBound(parrTemp , 1, &plUbound);

                    szPostData = new char[plUbound - plLbound + 2];
                     StrCpyN(szPostData, szTemp, plUbound - plLbound + 1);
                    szPostData[plUbound-plLbound] = '\0';
                    SafeArrayUnaccessData(parrTemp);

                    // Do something here with posted data!
                    //MessageBox(szPostData);

                    delete[] szPostData;
            }
            // Retrieve data from a Navigate to URL
            try
            {
                    csTestUrl = (CString)URL->bstrVal;
                    AfxExtractSubString(csEvent, csTestUrl, 0, (TCHAR)':');
                    AfxExtractSubString(csAction, csTestUrl, 1, (TCHAR)':');
                    AfxExtractSubString(csData, csTestUrl, 2, (TCHAR)':');
                    AfxExtractSubString(csQuestionMark, csTestUrl, 1, (TCHAR)'?');
            }
            catch(...) {}

            csEvent.MakeUpper();

            if ( csEvent != "EVENT" ){
                    // Do Nothing!
            }
            else
            {
                    try
                    {
                            csAction.MakeUpper();
                            if (csAction == "DRAG"){
                                    *Cancel = TRUE;
                                    //if (WM_LBUTTONDOWN && HTCLIENT && !::IsZoomed(GetSafeHwnd())){}
                                    ReleaseCapture();
                                    ::SendMessage(GetSafeHwnd(),WM_NCLBUTTONDOWN,HTCAPTION,NULL);
                                    //AfxGetApp()->OnIdle(0);   // updates user interface
                            }
                            else if (csAction == "RGN"){
                                    *Cancel = TRUE;
                                    CString csRgnPath = csSkinsDir + "regions\\" + csData + ".rgn"; 
                                    if ( FileExists( csRgnPath ) ){
                                            File2Rgn(GetSafeHwnd(), csRgnPath);
                                    }
                            }
                            else if (csAction == "MCLOSE"){
                                    *Cancel = TRUE;
                                    // Do some animation here
                            }
                            else if (csAction == "CLOSE"){
                                    *Cancel = TRUE;
                                    this->ShowWindow(SW_HIDE);
                                    this->m_WebBrowser.Stop();
                            }
                            else if (csAction == "CANCEL"){
                                    *Cancel = TRUE;
                                    ShowWindow(SW_HIDE);
                                    this->m_WebBrowser.Stop();
                            }
                            else if (csAction == "IEBROWSER"){
                                    *Cancel = TRUE;
                                    ShowWindow(SW_HIDE);
                                    this->m_WebBrowser.Stop();
                                    if ( !csData.IsEmpty() )
                                    {
                                            //ShellExecute(NULL, "open", sData, NULL, NULL, SW_SHOWNORMAL);
                                            // NOTE: BILL SERGIO
                                            // DON'T USE SHELLEXECUTE TO LAUNCH
                                            // USE SINK FUNCTION TO LAUNCH IE BROWSER
                                            ((CMainFrame*)m_pParent)->LauchIEBrowser(csData);
                                    }
                            }
                            else if (csAction == "MENUEXIT"){
                                    // TO QUIT THE ENTIRE APPLICATION FROM THIS EVENT IS NOT EASY!
                                    // YOU MUST LOAD A QUIT RES FILE AND NOT CANCEL THE LOAD
                                    // ADD A HANDLER IN OnDocumentComplete Event to process the
                                    // the loaded QUITRES resource or external quit file
                                    //*Cancel = TRUE;
                                    ShowWindow(SW_HIDE);
                                    this->m_WebBrowser.Stop();
                            }
                    }
                    catch( ... ) { *Cancel = TRUE; }
            }
    }

    The CORRECT WAY to prevent the right-mouse click from popping up a menu in a skin dialog is to add the following to the BODY tag:
    oncontextmenu="return false"
    Another subtle feature that you must address is that when you drag the skin around is the problem of a LARGE rectangle that appears around the skin as you drag it thanks to Microsoft's lack of attention to making things look good.  To solve this problem you need to the "SetViewWhileDrag" property and to make sure there is a registry entry for it as well.  This is done as follows:

    // Set registry "HKEY/Control Panel/Desktop/DragFullWindows" with string value "1"
    // and set "SystemParametersInfo"

    SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, 1, NULL, SPIF_SENDWININICHANGE);

    Skinned Video

    I could easily fill a book with techniques on playing video in different ways but I decided for the sake of illustration here to include a very simple wrapper for playing video.  The idea is that you can skin any window with a non-rectangular shape that you want to play video inside of and that window can be either one you created or any other apllication's window on the desktop. To illustrate the sample application let's you play video in the taskbar and some other places. 

    A simple way of playing video in a skin is to simply use an EMBED tag and play the video inside of the web page being used for the skin itself. If you want to apply a non-rectangular region to the EMBED tag so that another image in the .htm file can shape its region you can do this easily by setting the property of the embedded object to "windowless." 

    Another technique that I will illustrate in greater detail in an update to this article is to simply create a window dynamically inside of the skinned dialog and apply a region to it. 

    Multimedia programming in general is accomplished through a series of interfaces, or APIs that applications can utilize for this purpose. The Video.cpp class allows you to use the high-level interface based on the MCIWnd window class, and the mid-level interface called  the Media Control Interface, or MCI which provides a device-independent command-message and command-string interface for the playback and recording of audio and visual data.

    I spent a lot of time developing and perfecting ways of legally broadcasting large amounts of video to millions of computers without the need for any bandwidth using some clever peer-to-peer tricks, and I may post some of these techniques in a future article.

    The reader will have to supply their own sample videos, other than the "mouse.avi" that is included to test out some of the cool features in this project because I decided that packing cool sample video clips like "the chimp smelling his butt" would just make the zip file unnecessarily large. But I am sure the reader can come up with their own videos.

    System Tray

    Nothing fancy here except to note that we use the System Tray as the main controlling interface for the sample and that we must handle all of the mouse events in the MainFrame itself for a number of reasons. The most important thing to understand is that the new trend is to not use Microsoft's CMenu class for those typical crappy-looking popup menus, but instead to use a Skinned Modeless Browser Dialog which gives you incredible looking skinned menus over those of the CMenu class. 

    NOTE: While you are free to use the sample code, you may NOT use my names SlickSkins™, VideoSkins™, or VideoAnyWhere™, on anything you distribute. These are trademarks and copyrights of my company, William SerGio & Co., Inc. 

    And Finally...

  • In future articles I would like to discuss how to:
    • New techniques for broadcasting video to millions of computers in minutes using virtually no bandwidth! 
    • Create a COM DLL for displaying skins
    • Create TRUE alpha-channel video animations better than Microsoft's Agent
    • Add cool peer-to-peer features for legally sampling music videos
    • New skin techniques and skin creation tools for the Windows Media Player and Real Player
    • New skin techniques for creating multiple desktops in Windows 2000
    • Sample code to sink events from the Netscape's browser
    • How to add a dynamic translucent drop shadow to skins
    • How to display any streaming data like stock quotes or video in 3D Scaled Vector Graphical Displays that make it easier for people to read and view streaming data
    If you have any question, please feel free to contact me at:

    sergio@codearchive.com
    afilmmogul@aol.com
    Tel. 305-233-7654

     


     

    [Top] Rate this Article for us!     PoorExcellent  
    Hint: For improved responsiveness, use Internet Explorer 4 (or above) with Javascript enabled, choose 'Use DHTML' from the View dropdown and hit 'Set Options'.
     Keyword Filter
     View   Per page   Messages since
    New threadMessages 1 to 25 of 49 (Total: 49)First Prev Next Last
    Subject 
    Author 
    Date 
      To All
    Skonk 19:58 4 Mar 01 
      To writer
    Anonimus 12:54 22 Feb 01 
      excellent, great job, support u
    diablo 23:40 11 Feb 01 
      Good work Thank's
    Josan 6:48 1 Feb 01 
      FROM THE AUTHOR: Bill SerGio
    Bill SerGio, Author 6:14 1 Feb 01 
      Re: FROM THE AUTHOR: Bill SerGio
    lauren 9:16 1 Feb 01 
      Re: FROM THE AUTHOR: Bill SerGio
    Anonymous 12:54 1 Feb 01 
      Hmm
    Anonymous 23:32 31 Jan 01 
      I haven't had this much fun in ages...
    Anonymous 21:45 31 Jan 01 
      heyyyyyyyyyyyyyyyyy
    lauren 9:20 1 Feb 01 
      Your self promotion is in poor taste!
    Anonymous 21:03 31 Jan 01 
      Article of the month. :-)
    Anonymous 7:47 31 Jan 01 
      Re: Article of the month. :-)
    Jason De Arte 21:15 31 Jan 01 
      lol - newsgroup post is soooo funny
    Anonymous 7:38 31 Jan 01 
      Re: lol - newsgroup post is soooo funny
    Anonymous 7:44 31 Jan 01 
      but wait...
    lauren 9:23 1 Feb 01 
      Duh...
    FlamerBoy 3:05 30 Jan 01 
      Re: Duh... NO YOU JERK!
    Bill SerGio, Author 3:13 30 Jan 01 
      Re: Duh... NO YOU JERK!
    Anonymous 0:09 31 Jan 01 
      Re: Duh... NO YOU JERK!
    Anonymous 5:46 31 Jan 01 
      Re: Duh... NO YOU JERK!
    Anonymous 17:14 31 Jan 01 
      Re: Duh... NO YOU JERK!
    FlameBoy 19:25 31 Jan 01 
      I must admit...
    Anonymous 18:10 31 Jan 01 
      Re: I must admit...
    Anonymous 18:19 31 Jan 01 
      Re: I must admit... REPLY FROM AUTHOR
    Bill SerGio, Author 11:48 1 Feb 01 
    Last Visit: 12:00 Friday 1st January, 1999First Prev Next Last

    Home >> Dialog and Windows Programming >> Unedited Reader Contributions
    last updated 1 Feb 2001
    Article content copyright Bill SerGio, 2001
    everthing else © CodeProject, 1999-2001.
    The Code Project Click here for Dundas Software - 3D accelerated presentation quality ASP charting