Gimme Some Skin... VideoSkins

Introduction

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. 

The development time of Visual C++ applications is hampered by the time it takes to develop the GUI for the application. But if we use a non-rectangular, skinned Internet Explorer as our GUI for any Visual C++ application we drastically reduce the development time and add enormous funtionally to any application. In fact, a company's artist or web page designer can easily change or re-program an entire software application without the need for a programmer which reduces the maintenence of software applications drastically.  Skinned Internet Explorer interfaces can be displayed in any foreign language instantly including Chinese and Japanese without increasing the size of the executable file, and without the need for any additional programming.

In addition, a skinned application 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. And by making the screens of any application non-rectangular skinned Internet Explorer Interfaces, we make the application self-distributing and the perfect vehicle for Peer-to-Peer inter-application communications thus eliminating the need for any bandwidth beyond a dial-up 28.8 modem Internet connection needed by the company who distributes the software to conduct their entire Internet business.

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:

  • Dynamically Create Microsoft's WebBrowser Control in Modeless Skinned Dialogs 
  • Dynamically Create The WebBrowser Control in Any Window In Any Application
  • Use A Sink Library To Correctly Connect to Running Instances of Internet Explorer 
  • How To Resize Non-Rectangular Skin Regions Dynamically On Any Computer
  • Create Regions from Bitmaps, Save Regions to Files & Create Regions from Files
  • How To Play Video Anywhere In Any Window or In Any Shape 
  • Create New GUI Screens in Any Language INSTANTLY On Millions of Computers 
  • Connect Millions of Copies of This Software Via Peer-to-Peer Using DNS Datagrams
  • Many Skin Techniques & Tricks Never Seen Anywhere Before 

Application Structure

After you install the sample application make sure you set the pathways for the 2 projects inside of Visual Studio.  to do this go to the TOOLS menu in Visual Studio, then the OPTIONS menu, then select DIRECTORIES and set the pathways for the include files which are located in the VideoSkins directory, and the SinkLib directory.  If you fail to do this, then Visual Studio will not be able to find all of the include files.

The overall structure of this sample is indicated below:

The actual screen content, skin region, and functionality of any GUI screen can come from the installed application (client) or dynamically from any company's server or web page since the screen itself is just a modeless dialog hosting a non-rectangular, skinned instance of the Internet Explorer Web Browser Control.

Most software based dot com companies today use an Internet Application that will "listen" to running instances of Internet Explorer (and/or Netscape) to see if the user is on a "targeted" website indicated either by that website's URL or content. And if the user is on such a website, the Internet Application will spring into action providing some service or product to the customer. 

Most of these software applications really suck because they do not correctly "Sink" into Internet Explorer's events and because their Graphical User Interfaces(GUI) is hard coded and requires replacing the software to accommodate the rapid changes of an Internet environment. In addition, most of these applications are NOT "self-distributing" like Napster's software that distributes itself by word of mouth. 

I originally wrote my VideoSkins Peer-to-Peer Internet Application back in 1997, and made a lot of money marketing various versions of it to major corporations under many different names with many different "looks" for a wide variety of business applications. The sample here is a basic example of my VideoSkins

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

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.

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, 
                 UINT uBmpRes, 
                 CString csBmpFile, 
                 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)
    {
     try
     {
      csTestUrl = (CString)URL->bstrVal;
      AfxExtractSubString(csEvent, csTestUrl, 0, (TCHAR)':');
      AfxExtractSubString(csAction, csTestUrl, 1, (TCHAR)':');
      AfxExtractSubString(csData, csTestUrl, 2, (TCHAR)':');
      AfxExtractSubString(csQuestionMark, csTestUrl, 3, (TCHAR)':');
     }
     catch( ... )
     {
      return;
     }
     
     csEvent.MakeUpper();
     
     if ( csEvent != "EVENT" ) {return;}
     
     try
     {
      if ( csAction == "DRAG" ) 
      {
       *Cancel = TRUE;
       ReleaseCapture();
    
       // if (WM_LBUTTONDOWN && HTCLIENT
       // && !::IsZoomed(GetSafeHwnd()) ){}
    
       ::SendMessage(GetSafeHwnd(), WM_NCLBUTTONDOWN, HTCAPTION, NULL);
       // Update user interface if desired
       // AfxGetApp()->OnIdle(0);
      }
      // etc.
     }
     catch( ... )
     {
      return;
     }
    }
    

    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:

    <body... 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);
    

    Video AnyWhere

    This feature allows you to play video in ANY button, window, taskbar, popup, namely ANYTHING on your desktop!  Simply drag the video tool over what you want to play the video inside of and select the video!

    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. In a future update of this sample if there is any interest I might include some of those techniques.

    The reader will have to supply their own sample videos 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.

    "Internet Explorer Look-A-Like" MainFrame

    I decided to give users the ability to make the MainFrame window appear or dissappear and to make it look and behave exactly like the Internet Explorer Browser from Microsoft so users could distribute their own Internet Explorer look-a-like except for the change in logos.  This chamelion effect is controlled in the "videoskins.ini" file by setting the "ShowMainFrame" parameter to "1" to show the browser or "0" to hide it as follows:
    // Set the value of ShowMainFrame to turn 
    // on & off browser
    [Setup]
    ShowMainFrame=1
    
    The starting point I use for any Internet Application is a MainFrame Application where the "MainFrame" itself can be either hidden or used as one of the windows or screens in the application.  In this sample, I give the user the ability to make the MainFrame look exactly like Internet Explorer except for the Microsoft logo to provide a customizable "look-a-like" Internet Explorer Browser for users. This feature can be turned "on" or "off" in the file "videoskins.ini" that contains other setup parameters as well. 

    NOTE: All of your skins will be children of the MainFrame window which is perfect when you set "ShowMainFrame=no".  If you want to show the Internet Explorer "look-a-like" MainFrame window, and you do NOT want the skins to appear inside of the MainFrame window, simply create the skins from an invisible parent window that is parent to both the visible MainFrame and the skins.

    Most of the time you will never want to show the Internet Explorer "look-a-like" MainFrame window but simply use it ir an invisible parent for messaging.

    The idea is to use the message handling ability of the MainFrame to receive events from a "IE Event Sink" library reporting events in any running instance of Internet Explorer, process those events, and control the behavior of the Graphical User interface(GUI) which consists of Modeless Skinned Browser Dialogs. 

    IE Event Sink Library

    I created an IE Event Sink Library that I use in my applications instead of a dll to sink the events coming from multiple running instances of Internet Explorer. 

    Don't use a "Browser Helper Object" which the browser needs to instantiate to connect to the events of Internet explorer for many reasons including the fact that it is buggy and requires that if you really want it to work you need to place your registry entry ABOVE all of the other registry entries for helper objects.  However, you can use a browser helper dll to launch your software whenever the user launches Internet Explorer and/or an Explorer Shell but you would NEVER use it to connect or sink events of Internet explorer!  NEVER! 

    Get a reference to ShellWindows interface that keeps track of all the shell browsers (both Windows Explorer and Internet Explorer instances) that also notifies you whenever a new Explorer instance is created or deleted. 

    HRESULT thRes = 
     m_spSHWinds.CreateInstance(__uuidof(SHDocVw::ShellWindows));
    
    CSBOOL blnRes = 
     m_IEEventSink.Advise(m_spSHWinds, 
                          IID_IDShellWindowsEventSink);
    
    When you enumerate these Explorer instances, you can query whether as to whether the entry supports the IWebBrowser interface. If it does, it could either be a WebBrowser or a ShellBrowser. Once you obtain the IWebBrowser2 interface, you can either use that interface to manipulate (and communicate with) the Explorer instance or you can trap its events using the DWebBrowserEvents. 

    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. 

    Peer-to-Peer(P2P)

    Most of the many applications I've written included some form of Peer-to-Peer servers for both exchange of data as well as a means of distributing updates to millions of already installed applications without using any significant bandwidth. I left out the Peer-to-Peer sample code from this sample because it has too many good tricks that I did not want to give away at this time.  But this sample application has been structed to easily include any peer-to-peer code you want to add. Two important tricks that I learned with peer-to-peer is to model your peer-to-peer code on Network News Protocol (NNTP) since news servers are the best prototype you can find, and to use modified DNS datagrams for communication between the peers to determine what data files each peer has from any given peer. 

    All P2P communication must be asynchronous and non-blocking I don't recommend using Microsoft's CAsyncSocket because it's just as easy to write asynchronous I/O code straight to the Winsock API. In cases where you need to block, don't use Microsoft's CSocket class which is a subclass of CAsyncSocket that "fakes" blocking I/O using asynchronous sockets by using a message pump every time it gets a WSAEWOULDBLOCK error which can cause bizarre reentrancy effects. While CSocket is "blocking", it's pumping window messages, which allows a message to trigger another call to the blocking CSocket object.  Since true blocking sockets are easy to create using Winsock, why would you want to use buggy bogus blocking sockets instead of bug-free sockets that really block?

    Utilities

    In this sample I've placed the various utilities in MainFrame itself but you can create a separate COM DLL just for utility routines if you prefer which is what I've also done in many applcations.

    And Finally...

  • In future articles I would like to discuss how to:
    • 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
    • New techniques I developed for broadcasting video to millions of computers in just minutes using virtually no bandwidth! 

    If you have any question, please feel free to contact me.

    Downloads

    Download demo and source code - 605 Kb