Getting More Out of Your Browser Control - Part III
by
, 17-Apr-2011 at 03:42 AM (7526 Views)
This is the third blog article about getting more out of the web browser control. In comments I have been asked to show code that uses the web browser control. In the first blog I mentioned that the web browser control is used in a welcome dialog for Database Explorer. Let's review the code for that dialog in this blog.
The dialog
Let's look at the dialog again, the picture shows how it looks like.
The dialog is a Visual DataFlex ModalDialog object containing a cComWebBrowser, a checkbox and 2 button objects. The buttons can be used to browse to the next tip and to close the dialog. The checkbox is meant to please the user with an option to turn off the welcome dialog display.
Show Tips At Startup
The checkbox should write the user preference in a persistent way. For me there are three locations; 1) a table in your database with user preferences, 2) an INI file on disk or 3) in the Windows registry. In the following code I used the Windows registry. If the user toggles the state of the checkbox a true or false value will be directly written to the registry. I use the WriteDWord method of the cApplication object which places the preference in the HKEY_CURRENT_USER branch of the registry.
Using the registry is easy but if the user often uses a different computer and you do not store and restore the user settings via a network policy you are better off with one of the two other mentioned locations for storing the preference.Code:Object oShowTipsCheckBox is a CheckBox Set Size to 10 50 Set Location to 164 5 Set Label to "Show Tips at Startup" Set peAnchors to anBottomLeft Set Checked_State to True Procedure OnChange Boolean bChecked Get Checked_State to bChecked Send WriteDword of ghoApplication "Welcome" "ShowTips" bChecked End_Procedure End_Object
The Tips
As you can see in Database Explorer and the screenshot in the beginning of this blog it is possible for the user to browse through a set of tips. Tips are "little" text strings and need to be stored or read from somewhere. For Database Explorer I choose to store the tips inside the executable so that we do not depend on a file on disk but for the blog I created a table with tips. The advantage of a database table with tips is that you can easily modify the tips (extend, refresh). Another idea is to store the tips in a webservice. This way you can also keep track of how many different workstations are accessing your application because you can access the IP address. I would remove the option to turn off the show tips at startup if you want to use the feature as a kind of user access control.
The tips are stored in a table named Tips with two columns; an ID column for the tip number and a TEXT column for the text to be displayed. I made the TEXT column 512 characters in size.
The tip to be displayed is retrieved via a self defined method which I named FindNextTip. The method is called from when the first tip needs to be displayed in the cComWebBrowser object as well as from the button which lets the user browse to the next tip.Code:----------------------------------------------------------------------------- DATE: 17-04-2011 TIME: 09:59 PAGE: 1 FILE DEFINITION FOR FILE: Tips (# 1) ----------------------------------------------------------------------------- DRIVER NAME : DATAFLEX FILE ROOT NAME : Tips USER DISPLAY NAME : Tips DATAFLEX FILE NAME : Tips ----------------------------------------------------------------------------- RECORD LENGTH : 640 ( USED: 514 ) MAX NUMBER OF RECORDS : 10000 ( USED: 3 ) FILE COMPRESSION : NONE RE-USE DELETED SPACE : YES LOCKING TYPE : FILE HEADER INTEGRITY CHECKING : YES TRANSACTION TYPE : CLIENT ATOMIC RECORD IDENTITY INDEX : 0 ( 0 , 0 ) FILE LOGIN PARAMETER : SYSTEM FILE : NO ----------------------------------------------------------------------------- NUM FIELD NAME TYPE SIZE OFFST IX RELATES TO FILE.FIELD --- --------------- ---- ----- ----- -- --------------------------------- 1 ID NUM 4.0 1 1 2 Text TEX 512 3 INDEX# FIELDS DES U/C LENGTH LEVELS SEGMENTS MODE ------ --------------- --- --- ------ ------ -------- ------- 1 ID NO NO 2 2 1 ON-LINE
The source code I wrote for this is pretty straight forward for DataFlex developers and is:
With the piCurrentTip property I keep track of the current tip number and in the loop we randomly choose a tip number from the amount of records in the table. Instead of randomly pick a tip you could just take the next record and if you reach the end of the file go back to the beginning.Code:Procedure FindNextTip Integer iCurrentTip iTips iTip Get piCurrentTip to iCurrentTip Get_Attribute DF_FILE_RECORDS_USED of Tips.File_Number to iTips Repeat Move (Random (iTips) + 1) to iTip Clear Tips Move iTip to Tips.ID Find Eq Tips by 1 Until (Found and iTip <> iCurrentTip) Set piCurrentTip to iTip End_Procedure
Display the Tip
With the information from the previous blogs you can write the code for the cComWebbrowser object to find the location to replace with the text and ID of the current tips record. The code for the cComWebBrowser object used for this blog is:
The HTML instructions in the DataFlex strings above had to be cut in multiple blocks of text to avoid that the browser that you use to read this article tries to parse it as valid HTML.Code:Object oDisplay is a cComWebBrowser Set Size to 155 326 Set Location to 5 5 Set peAnchors to anAll { DesignTime = False } Property Integer piCurrentTip Object oHTMLDocument is a cComHTMLDocument End_Object Object oHTMLDivElement is a cComHTMLDivElement End_Object Procedure OnCreate String sImgSrc sHTML UChar[] ucHTML Variant vDocument Forward Send OnCreate Send ComNavigate "about:blank" 0 0 0 0 Get_File_Path "welcome.png" to sImgSrc Move ('<' + 'html>') to sHTML Move (sHTML + '<' + body style="font-family: Lucida Sans Unicode, Lucida Grande, Verdana, Arial, Helvetica, sans-serif; background-color:#C0DCFE; height: 100%; width: 100%; font-size: 11px;padding: 5px 10px 5px 10px;">') to sHTML Move (sHTML + '<' + 'div id="left" style="float: left;">') to sHTML Move (sHTML + '<' + 'img height="150" width="150" alt="welcome.jpg" src="' - sImgSrc - '"/>') to sHTML Move (sHTML + '<' + '/div>') to sHTML Move (sHTML + '<' + 'div id="right" style="float: left;">') to sHTML Move (sHTML + '<' + 'h1>Did You Know?<' + '/h1>') to sHTML Move (sHTML + '<' + div id="TipId" style="margin-bottom: 4px; font-style: italic;"> <' + '/div>') to sHTML Move (sHTML + '<' + div id="WelcomeTip"> <' + '/div>') to sHTML Move (sHTML + '<' + /div><' + '/body><' + '/html>') to sHTML Move (StrToWStr (sHTML)) to sHTML Move (StrToUCharArray (sHTML)) to ucHTML Get ComDocument to vDocument Set pvComObject of oHTMLDocument to vDocument Get ComOpen of oHTMLDocument "text/html" "replace" Nothing True to vDocument Set pvComObject of oHTMLDocument to vDocument Send ComWrite of oHTMLDocument ucHTML Send ComClose of oHTMLDocument Send ShowNextTip End_Procedure End_Object
In the OnCreate method above we create a default HTML page, light blue colored with a nice image on the left, a header for the text etc. Make sure that if you copy the code the div elements are lined up as in the example as a slightly longer text or bigger image can completely destroy the layout of the tip text page.
At the end of the OnCreate event we call a method named ShowNextTip which on its turn calls FindNextTip to locate a next tip record. In the ShowNextTip we locate the two div elements in the HTML page and replace the contents. The code for that is:
The full source code for the welcome / tip dialog is as follows:Code:Procedure ShowNextTip Variant vDocument vElement Send FindNextTip Get ComDocument to vDocument Set pvComObject of oHTMLDocument to vDocument Get ComGetElementById of oHTMLDocument "WelcomeTip" to vElement If (not (IsNullComObject (vElement))) Begin Set pvComObject of oHTMLDivElement to vElement Set ComInnerHTML of oHTMLDivElement to (Trim (Tips.Text)) End Get ComGetElementById of oHTMLDocument "TipId" to vElement If (not (IsNullComObject (vElement))) Begin Set pvComObject of oHTMLDivElement to vElement Set ComInnerHTML of oHTMLDivElement to (Sformat ("Tip: %1", Tips.ID)) End End_Procedure
Feel free to use the code above in your own applications.Code:Use Windows.pkg Use WelcomeHMTL.pkg Use CharTranslate.pkg Open Tips Set_Attribute DF_FILE_MODE of Tips.File_Number to DF_FILEMODE_READONLY // Function : StrToWStr // Purpose : Converts a OEM string to a Unicode string Function StrToWStr Global String sData Returns String Integer iLength iResult String sBuffer // Get size of buffer Move (MultiByteToWideChar(CP_OEMCP,0,AddressOf(sData),-1,0,0)) to iLength If (iLength = 0) Function_Return "" // Create output buffer Move (Repeat(Character(0),iLength*2)) to sBuffer // Do actual conversion Move (MultiByteToWideChar(CP_OEMCP,0,AddressOf(sData),-1,AddressOf(sBuffer),iLength)) to iResult If (iResult = 0) Function_Return "" Function_Return sBuffer End_Function Function StrToUCharArray Global String sDataIn Returns UChar[] Integer iLength UChar[] ucResult Address aResult Move (Length (sDataIn)) to iLength Move (ResizeArray (ucResult, iLength)) to ucResult Move (AddressOf (ucResult)) to aResult Move sDataIn to aResult Function_Return ucResult End_Function Object oWelcomeDialog is a ModalPanel Set Size to 180 337 Set Label to "Welcome" Set piMinSize to 89 211 Set Location to 2 2 Procedure Page_Object Boolean bPage Forward Send Page_Object bPage If (bPage) Begin Set Icon to "Default.Ico" End End_Procedure Object oNextTipButton is a Button Set Label to "&Next Tip" Set Location to 164 227 Set peAnchors to anBottomRight Set Default_State to True Procedure OnClick Send ShowNextTip of oDisplay End_Procedure End_Object Object oCloseButton is a Button Set Label to "&Close" Set Location to 164 282 Set peAnchors to anBottomRight Set Default_State to True Procedure OnClick Send Close_Panel End_Procedure End_Object Object oDisplay is a cComWebBrowser Set Size to 155 326 Set Location to 5 5 Set peAnchors to anAll { DesignTime = False } Property Integer piCurrentTip Object oHTMLDocument is a cComHTMLDocument End_Object Object oHTMLDivElement is a cComHTMLDivElement End_Object Procedure OnCreate String sImgSrc sHTML UChar[] ucHTML Variant vDocument Forward Send OnCreate Send ComNavigate "about:blank" 0 0 0 0 Get_File_Path "welcome.png" to sImgSrc Move ('<' + 'html>') to sHTML Move (sHTML + '<' + body style="font-family: Lucida Sans Unicode, Lucida Grande, Verdana, Arial, Helvetica, sans-serif; background-color:#C0DCFE; height: 100%; width: 100%; font-size: 11px;padding: 5px 10px 5px 10px;">') to sHTML Move (sHTML + '<' + 'div id="left" style="float: left;">') to sHTML Move (sHTML + '<' + 'img height="150" width="150" alt="welcome.jpg" src="' - sImgSrc - '"/>') to sHTML Move (sHTML + '<' + '/div>') to sHTML Move (sHTML + '<' + 'div id="right" style="float: left;">') to sHTML Move (sHTML + '<' + 'h1>Did You Know?<' + '/h1>') to sHTML Move (sHTML + '<' + div id="TipId" style="margin-bottom: 4px; font-style: italic;"> <' + '/div>') to sHTML Move (sHTML + '<' + div id="WelcomeTip"> <' + '/div>') to sHTML Move (sHTML + '<' + /div><' + '/body><' + '/html>') to sHTML Move (StrToWStr (sHTML)) to sHTML Move (StrToUCharArray (sHTML)) to ucHTML Get ComDocument to vDocument Set pvComObject of oHTMLDocument to vDocument Get ComOpen of oHTMLDocument "text/html" "replace" Nothing True to vDocument Set pvComObject of oHTMLDocument to vDocument Send ComWrite of oHTMLDocument ucHTML Send ComClose of oHTMLDocument Send ShowNextTip End_Procedure Procedure FindNextTip Integer iCurrentTip iTips iTip Get piCurrentTip to iCurrentTip Get_Attribute DF_FILE_RECORDS_USED of Tips.File_Number to iTips Repeat Move (Random (iTips) + 1) to iTip Clear Tips Move iTip to Tips.ID Find Eq Tips by 1 Until (Found and iTip <> iCurrentTip) Set piCurrentTip to iTip End_Procedure Procedure ShowNextTip Variant vDocument vElement Send FindNextTip Get ComDocument to vDocument Set pvComObject of oHTMLDocument to vDocument Get ComGetElementById of oHTMLDocument "WelcomeTip" to vElement If (not (IsNullComObject (vElement))) Begin Set pvComObject of oHTMLDivElement to vElement Set ComInnerHTML of oHTMLDivElement to (Trim (Tips.Text)) End Get ComGetElementById of oHTMLDocument "TipId" to vElement If (not (IsNullComObject (vElement))) Begin Set pvComObject of oHTMLDivElement to vElement Set ComInnerHTML of oHTMLDivElement to (Sformat ("Tip: %1", Tips.ID)) End End_Procedure End_Object Object oShowTipsCheckBox is a CheckBox Set Size to 10 50 Set Location to 164 5 Set Label to "Show Tips at Startup" Set peAnchors to anBottomLeft Set Checked_State to True Procedure OnChange Boolean bChecked Get Checked_State to bChecked Send WriteDword of ghoApplication "Welcome" "ShowTips" bChecked End_Procedure End_Object On_Key Key_Alt+Key_C Send KeyAction of oCloseButton On_Key Key_Alt+Key_N Send KeyAction of oNextTipButton End_Object