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…
- 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.