By R. Thirupathi MCA., Lecturer in Computer Science, KCCS Warangal


Introduction to Website design
HTML stands for Hyper Text Markup Language, which is used to create web pages that can be viewed from any browser. Browser is application software which is used to view web pages. There are many types of browsers available in the market. Some of those are Microsoft’s Internet Explorer, Netscape Navigator, NCSA Mosaic, Opera, Lynx( Unix based), HotJava(Sun Micro Systems), Mozilla Firefox……. Many Editors are available to write an html file. Some of the editors are Microsoft FrontPage, Netscape Composer, HoTMetaL Pro, Hot Dog Pro, Adobe PageMill,W3C’s Amaya, ……………….. We can also create an html file with windows notepad, dos editor. But we have to give the extension .html or .htm explicitly while saving the file. HTML consists of many number of tags. Tag is an entity which is interpretable by a browser (user agent) and enclosed between angular braces i.e. less than and greater than signs. The content which is enclosed between an opening and closing tag is called an element. Tag may consist an opening and closing. A tag is said to be independent, if it doesn't require closing. For example the tags <P>, <Br>, <Img> do not require closing. So these are called independent tags. The other are called dependent tags. Structure of an HTML Program

<html> <head> …………………………………………… …………………………………………… </head> <body> …………………………………………… …………………………………………… </body> </html>
Every tag consist some number of attributes. Attribute is an entity which enhances or controls the format, structure or appearance of an element in a web page.

e.g. <body bgcolor=red background=”path of the picture”>

By R. Thirupathi MCA., Lecturer in Computer Science, KCCS Warangal


Working with styles We can format the appearance of any element by the following ways. 1. 2. 3. 4. 5. Inline Styles Embedded Styles Style Classes Applying Styles to specified element IDs External Style Sheets Within a tag with style attribute With Style Tag With Style Tag and with a period (.) With Style Tag and with #Element Id .css (Cascading Style Sheet)

body{background-color:rgb(125,120,65);font-family:times new roman, verdana, arial; background-image:url("c:\windows\web\wallpaper\azul.jpg"); background-repeat:norepeat} a:link{color:magenta} a:active{color:chocolate} a:visited{color:yellow} a:hover{color:aqua} h1{color:red} h2{color:blue} h3{color:green} p{font-style:italic} <html> <head> <link rel="stylesheet" href="external.css"> <title>External Style Sheets</title> </head> <body> <h1 align=center><a href="Pictures\">View Pictures</a></h1> <h2><a href="Videos\">View Videos</a></h2> <h3><a href="Trimmed Songs\">View Songs List</a></h3> <br> <p>what r u doing? </body> </html>


Working with Dialog Boxes. <html> <head> <title>Working with Dialog Boxes</title> </head> <body> <script language=JavaScript>

By R. Thirupathi MCA., Lecturer in Computer Science, KCCS Warangal

i++) document. ……. } e.appName=="Microsoft Internet Explorer") { alert("U R Working with MS IE") if(confirm("Do U want to check whether a number is even or odd")) { var x=prompt("Enter anumber") if(x%2==0) document.write(i+" ") } By R. which can be written once and may be used as many times as we want. KCCS Warangal -4- .. …………….WEB AND VISUAL PROGRAMMING (VC++ 6.i<=n2. Lecturer in Computer Science.n2) { for(var i=n1. arg-2.writeln("The given Number "+ x +"is an Even Number") else document. function naturals(n1.0) if(navigator.. Thirupathi MCA.g. function function-name(arg-1.) { ……………. …………….writeln("The given Number "+ x +"is an Odd Number") } } </script> </body> </html> Functions: Function is a sub program.

writeln("<br><br>After Sorting: <br>") for(var i=0.WEB AND VISUAL PROGRAMMING (VC++ 6. Lecturer in Computer Science.g.0) Array Class: Array is a collection of homogeneous data items that are stored consecutively in the memory. var x = new Array concat pop push reverse sort toString valueOf e. KCCS Warangal -5- .i<a. Thirupathi MCA.push(25) a.pop( ) document. <html> <head> <title> Program on Arrays </title> <script language=javascript> var a = new Array var b = new Array var c = new Array var d = new Array var total = 0 a[0] = 10 a[1] = 9 a[2] = 8 a[3] = 7 a[4] = 6 a.writeln("<br>a[ "+i+" ] = "+a[i]) total = total + a[i] } d[0] = 32 d[1] = 41 d[2] = 52 d[3] = 7 d[4] = 86 b=a.writeln("<center><font color=navy size=5>Before Sorting: <br>") for(var i=0. which share a common name.sort( )).i<b.length.concat(d. The elements are identified by an index or sub script value.sort( ) c=a.i++) By R.sort( ) document.length.i++) { document..

.writeln("<font color=coral size=4><ol type=1>") for(var prop in document) { document.i<c.writeln("<br><center><font color=navy size=5>b[ "+i+" ] = "+b[i]) document.WEB AND VISUAL PROGRAMMING (VC++ 6. Lecturer in Computer Science.writeln("<br><br>After Concatination: <br>") for(var i=0.writeln("</ol>") </script> </body> </html> By R.i++) document.writeln("<br><center><font color=navy size=5>c[ "+i+" ] = "+c[i]) document.0) document.writeln("<br><br><b>"+"The sum of elements is: "+total+"<br>") </script> </head> <body bgcolor=chocolate> </body> </html> Displaying Document Object’s Properties <html> <head> <title> Document Object's Properties </title> </head> <body bgcolor=navy leftmargin=25 rightmargin=25> <script language=JavaScript> document. KCCS Warangal -6- .length. Thirupathi MCA.writeln("<li>"+prop+" = "+document[prop]+"</li><br>") } document.

abs acos asin atan atan2 ceil cos exp floor log max min -7- pow random round sin sqrt tan By R.0) String Class: String is a sequence of characters that is it is an array of characters.fontsize(20).big()+"</u>") </script> Math Class: Math class contains the methods that are related to trigonometric. KCCS Warangal .writeln("<br><br>Length of the String is : <u>"+len+ “</u><br><br>Sub String : <u>" + sub. statistical operations.. Thirupathi MCA.length var sub=x.length-1) document.substring(2. Lecturer in Computer Science.fontcolor("blue").WEB AND VISUAL PROGRAMMING (VC++ 6.x.toUpperCase(). There is a built in class String in JavaScript which supports all the string operations.fontcolor("blue")+"</u>") var len=x.writeln("<b><center><font color=gold size=6>The String is : <u>"+x. var x = new String(“ramana”) big bold concat fontcolor fontsize indexOf <script language=javascript> italics replace small sub substring sup toLowerCase toUpperCase toString valueOf var x=new String("Strings") document.

getDate getDay getFullYear getHours getMilliSeconds getMinutes getMonth getSeconds getTime setDate setHours setMinutes setMonth setTime toDateString toString toTimeString By R. Lecturer in Computer Science. KCCS Warangal -8- .. Thirupathi MCA.WEB AND VISUAL PROGRAMMING (VC++ 6.0) Date Class: Date class contains the methods with which we can view or set date and time of the system.

ondblclick.speed) } } setInterval("scrollTheDocument()".top=dsoctop+parseInt(document.0) JavaScript JavaScript is an event driven object oriented scripting language. onkeydown. left=450"> <a href="javascript:" onmouseover="speed=scrollamount" onmouseout="speed=0"> <img name=up src=down.scrollLeft var dsoctop=document.color:navy. onmouseup.font-size:20pt"> 1 2 3 By R.body. Lecturer in Computer Science. onkeyup. Thirupathi MCA. <html> <head> <script> var Hoffset=190 var Voffset=300 var scrollamount=3 var speed=0 function scrollTheDocument() { var dsocleft=document.scrollTop b1. We can execute the methods on a specific event occurs on an element.gif height=50 width=50> </a> <br> <a href="javascript:" onmouseover="speed=-scrollamount" onmouseout="speed=0"> <img name=up src=up.. KCCS Warangal -9- . onmouseout. onreset.body.gif height=50 width=50> </a> </div> <pre style="font-family:verdana.body.scrollBy(0.left=parseInt(dsocleft)+parseInt(document.clientWidth)Hoffset+"px" b1.clientHeight )-Voffset+"px" if (speed!=0) { window. JavaScript supports events like onmouseover.body. onmousedown. onsubmit.WEB AND VISUAL PROGRAMMING (VC++ 6. onfocus. onkeypress. onclick. …….20) </script> </head> <body bgcolor=teal> <div id="b1" style="position:absolute.. top=300.style.style. onblur.

WEB AND VISUAL PROGRAMMING (VC++ 6.jpg" } var pathToImg=new Array() for (i=0. Thirupathi MCA.i++) { pathToImg[i]=new Image() pathToImg[i].i<bgimages. KCCS Warangal .} </style> </head> <body > <script language="JavaScript"> var bgimages=new Array() for (i=0.0) 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 </pre> </body> </html> Power point Slide Show Application <html> <head> <style> body{background-repeat: no-repeat. Lecturer in Computer Science.i++) { bgimages[i]=(i+1)+".10 - .background-position: center center.i<50.src=bgimages[i] } var inc=-1 function bgSlide() By R..length.

WEB AND VISUAL PROGRAMMING (VC++ 6.src window.1000) </script> <div style="position:absolute.defaultStatus=pathToImg[inc].0) { if (inc<bgimages. top=50.src } setInterval("bgSlide()". left=220"> <img id=pic height=450 width=600 border=5> </div> </body> </html> By R.src=pathToImg[inc]. Thirupathi MCA.. Lecturer in Computer Science.length-1) inc++ else inc=0 document.pic.all.11 - . KCCS Warangal .

if the registry editing is not done correctly. A web browser takes information from a user and sends it.WEB AND VISUAL PROGRAMMING (VC++ 6. Perl scripts can be written throgh notepad or DOS editor.pl.pl entry. the web browser directs the server to send specific data such as text.exe %s %s. Practical Extraction and Report Language (PERL) is a high level programming language developed by Larry Wall. Press Enter. CGI is standard for interfacing applications with a web server. The term client refers to a web browser. give the string as c:\perl\bin\perl. URLs are used by web browsers to indicate the name of the web server from which to request information and what information to reteieve for that server. A server-side CGI Script is then executed. Thirupathi MCA. These programs should be saved in a directory which has web sharing with all the access permissions and execute(including Scripts) permission. Select New String Value. to a web server. In the edit string dialog box give the absolute path for the perl interpreter . to the client. Be careful. By R. CGI applications may be written in many different programming languahges. For example if the perl is installed in C:\perl\bin\.pl in the editable text. CGI lets HTTP clients interact with programs across a netwrok through a web server. the system may not start properly. Type . images or other types of data to the browser. Permission is granted within the web server by a web master to allow specific programs to be exceuted on the web server. Lecturer in Computer Science. Double Click on the .0) CGI Perl Hyper Text Transfer Protocol (HTTP) is used by web browsers and web servers to communicate with one another. This inforamtion might be anything from credit card data to a person’s height. Then exit from the Registry.. using HTTP. To run CGI Perl scripts in the web server. Start regedit OK HKEY_LOCAL_MACHINE System CurrentControlSet Services W3Svc Parameters ScriptMap Right Click on the right pane. but extension should be . perehaps verifying credit card information. we should make modifications to the Windows Registry. KCCS Warangal . such as whether a credit card purchase is accepted or rejected. By issuing HTTP GET command. and sends back information.12 - .

.13 - . Thirupathi MCA. KCCS Warangal . Lecturer in Computer Science.0) By R.WEB AND VISUAL PROGRAMMING (VC++ 6.

These packages provide additional functions to the perl.\n". print "Adding an integer to a string yields: $b\n". print "Adding uninitialized variable num to 5 yields: $test. print "The value of variable a is: $a\n". Win32-Registry. Win32-ODBC. $b = "A string value". Lecturer in Computer Science. $a = 5.14 - . Win32-API. $test = $num + 5. print "Adding a string to an integer yields: $a\n".0) In addition to core perl package. there are several packages available like libwww-perl. print "Using a variable before initializing: $var\n". Thirupathi MCA. KCCS Warangal . $a = $a + 5.. By R.WEB AND VISUAL PROGRAMMING (VC++ 6.\n". libwww-perl Win32-API Win32-ODBC Win32-Registry XML-Parser Increases netrwork programming functionality Enables the programs to make Windows system calls Enables ODBC Connectivity within perl programs Allows to read and write to the Windows Registry Allows to parse XML Documents Program to illustrate the use of scalar variables. $a = $a + $b. print "Variable a after adding 5 is $a. $number = 7. $b = $b + $number. XML-Parser.

. " </HEAD>". Program to display CGI environment variables use CGI qw/:standard/. " WIDTH = 100%>".. use Win32::ODBC. print " </BODY>". By R. print "letters from capital A to Z:\n\n". Program to query a database and send results to the client. print "<TD BGCOLOR = #11BBFF><BIG>$key</BIG></TD>". " <BASEFONT FACE = \"ARIAL. use CGI qw/:standard/. @array2 = (A. print "The array contains:\n\n". "Bobby".Z). print "<TD><FONT COLOR = BLACK SIZE = 2>$ENV{$key}". " <TABLE BORDER = 0 CELLPADDING = 2 CELLSPACING = 0". print "</Font></TD>"..</TITLE>". print "</HTML>".SANS-SERIF\" SIZE = 2>". print "The range operator is used to store all\n". "Sue". print print print print print print print print print header. foreach $key (sort keys %ENV) { print "<TR>". " <HEAD>".0) Program to demonstrate arrays in Perl @array = ("Bill". " <BODY TEXT = BLACK BGCOLOR = WHITE>".15 - .WEB AND VISUAL PROGRAMMING (VC++ 6. "<HTML>". Thirupathi MCA. print "</TR>". " <TITLE>Environment Variables. KCCS Warangal . my $querystring = param(QUERY). Lecturer in Computer Science. print "@array2 \n". "Michelle"). print "@array \n\n".. print "Third element: $array[2]\n\n". } print " </TABLE>".

"and Associates.16 - .WEB AND VISUAL PROGRAMMING (VC++ 6. Lecturer in Computer Science. $counter++. if (!($Data = new Win32::ODBC($DSN))) { print "Error connecting to $DSN\n". print "<BASEFONT FACE = \"ARIAL. } print "<BODY>". "<BR>Your search yielded <B>$counter</B> results. } print "</TR>". "\n". $Data->Close(). print "Error: " . "<A href = \"mailto:deitel\@deitel. KCCS Warangal . exit. print "<TR>".</A>. } if ($Data->Sql($querystring)) { print "SQL failed.. exit.\n". foreach $key( keys( %Data ) ) { print "<TD BGCOLOR = #9999CC>$Data{$key}</TD>".". print "<FONT COLOR = BLUE SIZE = 4> Search Results </FONT>".". "<FONT SIZE = 2>". while($Data->FetchRow()) { %Data = $Data->DataHash(). "<BR><BR>". "\n". $Data->Error() . end_html. print "Error: " .SANS-SERIF\" SIZE = 3>". Inc.com\">Deitel ". print "<TABLE BORDER = 0 CELLPADDING = 5 CELLSPACING = 0>".0) $DSN = "Products". @key_entries = keys(%Data). "Please email comments to ". "</TABLE>". } print print print print print print print print By R. Thirupathi MCA. Win32::ODBC::Error() . print header. $counter = 0.

print "<BODY>".pl"> <input type = "text" name = "query" size = 40 value = "select * from authors"><br><br> <input type = "submit" value = "Send Query"> </form> </body> </html> Program to read information sent to the server from the FORM use CGI qw/:standard/. print header. print ". $email = param(EMAIL). print "<TABLE BORDER = 0 CELLPADDING = 0".WEB AND VISUAL PROGRAMMING (VC++ 6. $os = param(OS).0) $Data->Close(). print "mailing list. <html> <head> <title>Sample Database Query</title> </head> <body> <basefont face = "Arial. $book = param(BOOK).</big> </font><br> <form method = "post" action = "cgi-bin/data. By R. Lecturer in Computer Science. print "<FONT COLOR = BLUE><BIG>$book </BIG></FONT>".SANS-SERIF\" SIZE = 3>". if ( $phone =~ / \( \d{3} \) \d{3} . print "<BIG>The following information has been saved ". print "<BASEFONT FACE = \"ARIAL. $firstname = param(FNAME).\d{3} /x ) { print "Hi <FONT COLOR = BLUE><B>$firstname</B></FONT>". Thank you for completing the survey..<BR><BR>". sans-serif" size = 2> <font size = +2> <big>Querying an ODBC database. $phone = param(PHONE). print "You have been added to the ". print "in our database:</BIG><BR>". $lastname = param(LNAME).<BR>". Thirupathi MCA. KCCS Warangal .17 - .

"Thank You.. "<TR><TD>$firstname $lastname</TD><TD>$email</TD>". "</FONT></CENTER>". <head> <title>Sample FORM to take user input in HTML</title> </head> <body> <basefont face = "arial. "<TR><TD BGCOLOR = #FFFFAA>Name </TD>". "<BR><BR><BR>".18 - . " <TD BGCOLOR = #FFFFCC>Phone</TD>". "<TD>$phone</TD><TD>$os</TD></TR>". "This is only a sample form.pl"> <img src = "images/user. " A valid phone number must be in the form". "<FONT COLOR = RED SIZE = +2>".0) print print print print print print print print print print print print print } else { print print print print print print print } <html> " CELLSPACING = 10>". ".<br> </font> <img src = "images/fname. "</TABLE>". "<CENTER><FONT SIZE = -3>". "<FONT COLOR = BLUE> Click the Back button. "You have not been added to a mailing list.gif"><br> <font color=blue> Please fill out the fields below. <form method = "post" action = "/cgi-bin/form.". " <TD BGCOLOR = #FFFFBB>Email</TD>". Lecturer in Computer Science. KCCS Warangal . Thirupathi MCA.</big> </font><br> Please fill in all fields and click Register.<BR><BR>".". ". "enter a valid phone number and resubmit.gif"> <input type = "text" name = "fname"><br> By R.sans-serif" size = 2> <font size = +2> <big>This is a sample registation form. "INVALID PHONE NUMBER</FONT><BR>".WEB AND VISUAL PROGRAMMING (VC++ 6. "<BIG>(555)555-5555</BIG>". " <TD BGCOLOR = #FFFFDD>OS</TD></TR>".

0) <img src = "images/lname.gif"><br> <font color = blue> Which book would you like information about?<br> </font> <select name = "book"> <option>Internet and WWW How to Program <option>C++ How to Program 2e <option>Java How to Program 3e <option>Visual Basic How to Program 1e </select> <br><br> <img src = "images/os. KCCS Warangal . Lecturer in Computer Science.19 - ..gif"> <input type = "text" name = "email"><br> <img src = "images/phone.WEB AND VISUAL PROGRAMMING (VC++ 6. Thirupathi MCA.gif"><br> <font color = blue> Which operating system are you currently using?<br> </font> <input type = "radio" name = "os" value = "Windows NT" checked> Windows NT <input type = "radio" name = "os" value = "Windows 95"> Windows 95 <input type = "radio" name = "os" value = "Windows 98"> Windows 98<br> <input type = "radio" name = "os" value = "Linux"> Linux <input type = "radio" name = "os" value = "Other"> Other<br> <input type = "submit" value = "Register"> </form> </body> </html> By R.gif"> <input type = "text" name = "lname"><br> <img src = "images/email.gif"> <input type = "text" name = "phone"><br> <font size=-2> Must be in the form (555)555-5555<br><br> </font> <img src = "images/downloads.

$path. $server_domain = "127. print "Height". ". $server_domain. "<FONT COLOR = BLUE>Favorite Color:</FONT> ". KCCS Warangal . "<BASEFONT FACE = \"ARIAL.0. "<FONT COLOR=BLUE>Name:</FONT> $name <BR>". path=". path=".</b> </font><br> <form method = "post" action = "cgi-bin/cookies. print "Set-Cookie: ". ".WEB AND VISUAL PROGRAMMING (VC++ 6. "\n". domain=". "=". $expires. $expires = "Monday. expires=". "<BODY>".20 - . print print print print print print print print print header.pl"> <big>Name:</big><br> <input type = "text" name = "name"><br> <big>Height:</big><br> <input type = "text" name = "height"><br> By R. "=".0) Program to write a cookie to a client’s machine use CGI qw/:standard/. ". my $name = param(NAME). <html> <head> <title>Writing a cookie to the client computer</title> </head> <body> <basefont face = "arial. $expires. $color. ". $expires.sans-serif" size = 2> <font size = +2> <b>Click Write Cookie to save your cookie data.0. $height. print "Set-Cookie: ". expires=". "<FONT COLOR = BLUE>Height:</FONT> $height<BR>". my $height = param(HEIGHT). $path. domain=". ". $path.SANS-SERIF\" SIZE = 3>". "The cookie has been set with the folowing data:". "<FONT COLOR = $color> $color<BR>". "=". ". print "Color". Lecturer in Computer Science. domain=". print "Set-Cookie: ". path=". expires=". ". ". Thirupathi MCA. $path = "". $name. "<BR><BR>". $server_domain. $server_domain. ".. "\n". my $color = param(COLOR). print "Name". "\n". 20-Dec-99 16:00:00 GMT".1".

while(<FILE>) { my @data = split(/\n/). print "<BASEFONT FACE = \"ARIAL. print "http://$url/". Lecturer in Computer Science./. foreach $entry (@data) { my ($data.21 - . my $search = param(SEARCH). print "<BR>$data<BR><BR>". } print "<A HREF=\"http://$url/\">". "urls.0) <big>Favorite Color</big><br> <input type = "text" name = "color"><br> <input type = "submit" value = "Write Cookie"> </form> </body> </html> Program to search for Web pages use CGI qw/:standard/. Thirupathi MCA. if ($data =~ /$search/i) { if ($counter == 0) { print "<BIG>Search Results:<BR><BR></BIG>". KCCS Warangal . open(FILE.txt") || die "The URL database could not be opened". my $counter = 0. $entry).SANS-SERIF\" SIZE = 3>". print "</A>". $url) = split(/. } } } By R.WEB AND VISUAL PROGRAMMING (VC++ 6. $counter++. print header..

KCCS Warangal . Inter.mail.smskwik..google.www. } Sample data of urls. } else { print "<BIG>$counter matches found for </BIG>". .www.22 - .www.net AICTE Website.sans-serif" size = 2> <font size = +2> <big>Enter a search string and click Find.org Sending Instant SMS to any Mobile in India..www.0) close FILE..monster.www. print "<FONT COLOR = BLUE>$search</FONT>".com Eenadu Dily News Paper.lekhini.kakatiya.naukri.www.txt file For Web Search.in For more examination results like SSC.com <html> <head> <title>A Simple Search Engine</title> </head> <body> <basefont face = "arial.www.in Google Mail..com Yahoo Mail.com Rediff Mail.ac.com Official Website of Kakatiya University.www.www.gmail.aicte. Thirupathi MCA. if ($counter == 0) { print "<B>Sorry.pl"> By R.ernet.manabadi.www. ". Lecturer in Computer Science.www.eenadu.rediffmail.</big> </font><br> <form method = "post" action = "cgi-bin/search..WEB AND VISUAL PROGRAMMING (VC++ 6.com Monster Job Search.www. print "<FONT COLOR = BLUE>$search</FONT>.gov Online Telugu Script.www..aponline.com Andhra Pradesh State Government Website. no results were found matching </B>".yahoo.com Naukri Job Search.

$DSN = "Products".0) <input type = "text" name = "search"><br> <input type = "submit" value = "Find"> </form> </body> </html> Using ODBC to Connect to a Database use Win32::ODBC. @key_entries = keys(%Data).23 - . $Data->Close(). print "<TR>". Lecturer in Computer Science.\n". "\n". } print "<BODY>". Win32::ODBC::Error() . print "Error: " .. my $querystring = param(QUERY). exit. } if ($Data->Sql($querystring)) { print "SQL failed. print "<TABLE BORDER = 0 CELLPADDING = 5 CELLSPACING = 0>". "\n". Thirupathi MCA. By R. exit. while($Data->FetchRow()) { %Data = $Data->DataHash(). print header. KCCS Warangal . print "<FONT COLOR = BLUE SIZE = 4> Search Results </FONT>".WEB AND VISUAL PROGRAMMING (VC++ 6. foreach $key( keys( %Data ) ) { print "<TD BGCOLOR = #9999CC>$Data{$key}</TD>". use CGI qw/:standard/.SANS-SERIF\" SIZE = 3>". $Data->Error() . if (!($Data = new Win32::ODBC($DSN))) { print "Error connecting to $DSN\n". $counter = 0. print "<BASEFONT FACE = \"ARIAL. print "Error: " .

</A>.pl"> <input type = "text" name = "query" size = 40 value = "select * from authors"> <br><br> <input type = "submit" value = "Send Query"> </form> </body> </html> By R. Lecturer in Computer Science.</strong> </font><br> <form method = "post" action = "cgi-bin/data.24 - .WEB AND VISUAL PROGRAMMING (VC++ 6. end_html.sans-serif" size = 2> <font size = +2> <strong>Querying an ODBC database..0) } print print print print print print print print } print "</TR>". "Please email comments to ". $Data->Close(). Inc.".". <html> <head> <title>Sample Database Query</title> </head> <body> <basefont face = "arial.com\">Ramana ". "<BR><BR>". "<BR>Your search yielded <B>$counter</B> results. "</TABLE>". KCCS Warangal . "<FONT SIZE = 2>". Thirupathi MCA. "<A href = \"mailto:mramanakar@gmail. $counter++. "and Associates.

0) UNIT-II VISUAL PROGRAMMING By R.. KCCS Warangal . Thirupathi MCA. Lecturer in Computer Science.25 - .WEB AND VISUAL PROGRAMMING (VC++ 6.

0. and it takes advantage of IntelliSense features originally released as part of Visual Basic. The development system includes new enhancements to MFC. These enhancements include classes for Internet programming and support for new common controls introduced in Internet Explorer 4. which greatly improves your efficiency. Database Programming and Design Performance analysis and team based development support Themes of Microsoft Visual Studio 6. The Developer Studio Editor is much improved.0) Microsoft Visual C++ 6. The debugger included with Visual C++ includes a new feature called Debug and Continue.0 Edit and continue debugging Intellisence technology Supports for MTS (Microsoft Transaction Server) Supports for Internet development By R. An improved online help system puts the MSDN in easy reach. Thirupathi MCA. These features include statement completion. which enables you to make small changes while debugging and then immediately continue debugging without restarting the application. Boolean types are supported.WEB AND VISUAL PROGRAMMING (VC++ 6.26 - .0 Visual C++ offers many new features and improvements over its predecessor.0 Complete suit of tools for component based development Enhanced life-cycle Productivity Enterprise database tools Enhanced support for teams Integration with middle-tier application services VC++ Specific Improvements in Version 6. Microsoft Visual Studio 6. KCCS Warangal . and template support is improved. Visual C++ 5. The compiler offers improved support for the ANSI C++ standard. just a mouse click away.0 Specifics It Includes DNA Application Development Integrated tools for Multi tier Application Design User Interface Development Middle-Tire Component Development Assembly.. The online help system automatically uses the latest version of the MSDN Library if it's installed on your computer. the Microsoft Foundation Class Library.0 and Windows 98. Lecturer in Computer Science.

These workspaces represent a particular set of projects. when used as intended. In order to take advantage of these features. It is a complete application development environment that. linking. including source file creation. Lecturer in Computer Science. debugging.0) HTML.WEB AND VISUAL PROGRAMMING (VC++ 6. to an entire suite of applications. Introduction to VC ++ environment Visual C++ is much more than a compiler.0. you should see a screen similar to the one shown Microsoft Developer Studio should be added to your start menu under Programs. lets you fully exploit the object oriented nature of C++ to create professional Windows applications. KCCS Warangal .0 Toolbars You will notice that several different toolbars are used in Developer Studio. By R. The Project Workspace Working with the Developer Studio is based on working with Project workspaces. Thirupathi MCA. you need to understand the C++ programming language Integrated Development Environment Visual C++ 6.0 includes the Microsoft Developer Studio Integrated Development Environment (IDE). to a function library. Microsoft Visual Studio 6. resource editing. compiling. When you first start Microsoft Developer Studio. Microsoft Visual C++ 6.. Most of these will normally dock at the top of the window. DHTML New database supports OLEDB Miscellaneous improvements to the environment. although you may drag the frame of the toolbar anywhere you like. which can be anything from a single application. and many other useful features. This environment is the centerpiece of most any interaction you will have with your C++ projects.27 - .

ATL COM AppWizard This is used to create a new project based on the Active Template Library (ATL). This project type is available only in Visual C++ Enterprise Edition. You may also start up one of the Application Wizards from this dialog box. Custom AppWizard This type of project will allow you to create your very own AppWizard. Cluster Resource Type Wizard This type of wizard is used to create a workspace that contains two projects that are used with Microsoft Cluster Server (MSCS). By R. One of the projects is used to create a resource DLL. which may then be used to help you create additional projects. 2.WEB AND VISUAL PROGRAMMING (VC++ 6. which extends the MSCS Cluster Administrator. The other project is a Cluster Administrator Extension DLL. using ATL. Database Project This type of project allows you to test stored SQL procedures directly. 1. This type of project then allows you to add your own COM objects. so let's take a brief look at what Visual C++ will do for you when you choose each project type. without going through the process of creating an ODBC application. Thirupathi MCA. part of Windows NT Enterprise Edition.0) When you create a new project. 4. Lecturer in Computer Science. Visual C++ will set up default build settings for the type of project you specify here.28 - .. a cluster-aware application. Project Types The New Project Workspace gives you the opportunity to create several different types of projects. KCCS Warangal . 3. which is used by MSCS to manage a resource—typically. allowing a user to manage the interaction between MSCS and the resource.

6. you should use this project type. ISAPI Extension Wizard This wizard allows you to easily create the framework required to create extensions to Internet Information Server. but you will need to add functionality to it.WEB AND VISUAL PROGRAMMING (VC++ 6.29 - . Lecturer in Computer Science. By default. The project created implements the code needed to initialize a DLL that uses MFC. without creating one of the other project types to replace your makefile. "MFC Class Library Overview. 8.0) 5. You just need to add on the functionality specific to your application. 10. 9.. MFC ActiveX ControlWizard This AppWizard will help you to create the framework for a project that uses the Microsoft Foundation Classes to implement ActiveX controls. This project type is available only in Visual C++ Enterprise Edition. We will be looking at how to implement ActiveX controls in more detail in Chapter 28. An extended stored procedure is hosted in a Win32 DLL. MFC AppWizard (DLL) This will use the MFC AppWizard for DLLs to create a new dynamic link library project for you. By R. 11. 7. MFC AppWizard (EXE) This will start up the MFC AppWizard to help you create the framework for a full-blown MFC Windows application." but feel free to try it out if you like. If you have existing makefiles that you want to incorporate into a build from Visual C++. KCCS Warangal . This project may include the framework required to add a toolbar to Developer Studio.mak. as well as to handle events that occur within Developer Studio. Extended Stored Procedure Wizard This wizard allows you to create a SQL Server extended stored procedure. using the Internet Server API. We will look at this in more detail in Chapter 2. Thirupathi MCA. Makefile This project type is used to add a project that works with an external makefile. DevStudio Add-In Wizard This creates a new skeleton project that may be used to add commands to the Developer Studio environment. The skeleton application created by AppWizard is a complete application in that it will build and run. The project settings will allow you to specify the command line that you want to execute to build this project. this is NMAKE /f myMake.

A simple Hello World project that contains one main source file.. Each Win32 project type will set up the default project settings for creating a Win32 DLL. A simple wizard is provided that enables you to build four types of generic console applications: An empty project containing no source files. This type of project is useful as a master project for several subprojects in a workspace.30 - . the program immediately exits. 14. This project type is appropriate for commandline utilities and other applications that do not have a graphical user interface. Thirupathi MCA. A simple project with one main source file. 13. but uses a standard command window. such as classes and variables. This project contains a resource file in addition to the main source file. Win32 Console Application This project type will create a new project with the build settings appropriate for building console applications. By R. KCCS Warangal . When launched. 15. Files dialog box. You will need to add your own source files before building this project type. Win32 Application The application project uses a very simple wizard that enables you to build three types of generic Win32 applications: A simple project with no source files included by default A typical generic Win32 project with one C++ source file A simple Win32 application that displays Hello World. A project that has one main source file and has examples of how to export symbols.WEB AND VISUAL PROGRAMMING (VC++ 6. This type of application does not have a Windows graphical interface. A simple wizard allows you to choose from three types of Win32 DLLs: An empty project with no source files. You will have to add your existing source files to the new project with the Project. consisting of resource files and a C++ source file Each project has the default build settings for a Windows application. When launched. Add to Project. You must add your own source files before building this type of project.0) 12. Win32 Dynamic Link Library This project type will create a Win32 DLL. the program displays Hello World and exits.0 project for existing applications that you are moving to VC++ 6. A simple project that will support MFC. Lecturer in Computer Science. A simple project that contains one main source file.0. These types of projects are useful for creating a Visual C++ 6. Utility Project This project type is a generic container for any types of files or custom build steps you would like to have performed.

0) 16. Other Project Types You might also see additional project types listed. A simple wizard allows you to specify if you would like to support pre-compiled headers or MFC in the project. By R. If you do not. The ClassView As the name suggests. the ClassView displays a tree view of the classes that you have created for your project and allows you to expand the classes to reveal their member functions and variables. or that were provided by a third-party vendor and optionally loaded with Visual C++.lib). it was hidden the last time the workspace was open and can be brought to the foreground by selecting the Workspace command from the View menu or simply by pressing Alt+0. The Workspace Window When you open a project workspace you should see the Workspace window. 17. hence the name.31 - .WEB AND VISUAL PROGRAMMING (VC++ 6. Thirupathi MCA. KCCS Warangal . but the project settings are set to create a standard statically linked library (. The FileView You will notice immediately that the FileView will let you view the list of files in your projects. Win32 Static Library This is similar to the Dynamic Link Library option. What might not be quite so obvious is the fact that it provides a great deal of functionality designed to help you manage your files and projects. Lecturer in Computer Science. These are custom AppWizards that you have created..

Verify that N:\EAS230\Lab1\HelloWorld in the Location field and click OK. The context menu also allows a quick way to add member functions or variables by way of a simple dialog box Launching Microsoft Visual C++ 6. Your projects are opened when the workspace is opened.32 - . select the Workspaces tab. By R. KCCS Warangal .0) context menu: for a class allows several different choices for you to jump to the more powerful source code browser to examine how a class is used. In the new window that pops up. On the right hand side. Select Blank Workspace in the list. type in HelloWorld in the Project Name field.. then click OK.0 Creating a New Workspace Click on File → New in the toolbar. Select Win32 Console Application in the list.0 Click on Start → Programs → Microsoft Visual Studio 6. Select An Empty Project and click Finish in the next window. Thirupathi MCA. Opening an Existing Project Click on File → Open Workspace. go to N:\EAS230\Lab1 and select the Lab1. On the right hand side. then verify that N:\EAS230\Lab1 is in the Location field. Creating a New Project Click on File → New in the toolbar.0 → Microsoft Visual C++ 6. select the Projects tab. Select Add to current workspace. Click OK in the New Project Information window that pops up. In the new window that pops up.WEB AND VISUAL PROGRAMMING (VC++ 6. Lecturer in Computer Science.dsw file and click OK. Select N:\EAS230\Lab1\Lab1. Opening an Existing Workspace Click on File → Open in the toolbar. In the window that pops up. as well as lists of any base classes and derived classes associated with this class. type N:\EAS230 is in the Location field (this only needs to be done the first time you use VC++).dsw and click OK. then type Lab1 in the Workspace Name field. including direct access to the definitions and references for the class.

exe – 0 error(s).) Debugging C++ Source Code If you have compiler errors. Building and Runing a Project Save the code Compile the code by clicking on Build → Compile HelloWorld. Adding an Existing File to a Project Click on File → Open in the toolbar. If it links successfully. Make sure the source file is saved and then select the HelloWorld. Lecturer in Computer Science.WEB AND VISUAL PROGRAMMING (VC++ 6.cpp in the File Name field. This only removes the source file from the project and does not delete the actual source file.cpp. To see the error message first. If there are error messages.exe. the window at the bottom of your screen will display HelloWorld. the statement corresponding to the error message will be identified by a blue arrow in the coding window. select the Files tab. In the new window that pops up. Right click in the source code window and select Insert File Into Project → HelloWorld. In the window that pops up. 0 warning(s). You should see the file under Source Files in the Workspace. Thirupathi MCA. Click OK. Link the code by clicking on Build → Build HelloWorld. If it compiles successfully. A window should popup with the output from your program in it: Hello World!!! Press any key to continue (Note: this line is put in automatically by VC++. on the plus sign in front of Source Files.cpp file and hit delete.cpp. see the section on Debugging C++ Source Code below.. Recompile the program.obj. Return to the coding window and correct the error. If you double click on an error message. On the right hand side click Add to project and select HelloWorld and type in HelloWorld. Click on the plus sign next to HelloWorld files. Click on the plus sign next to HelloWorld files and on the plus sign in front of Source Files. Click on the File View Tab in the Workspace.obj – 0 error(s). Removing a File from a Project Click on the File View Tab in the Workspace.33 - . go to N:\EAS230\Lab1\HelloWorld and select the HelloWorld.cpp file and click Open.0) Adding a New Source File to a Project Click on File → New in the toolbar. 0 warning(s). By R. Execute the code by clicking on Build → Execute HelloWorld. KCCS Warangal . click the mouse in the window at the bottom of your screen. scroll to the top of that window. Select C++ Source File in the list. and then on HelloWorld. the window at the bottom of your screen will display HelloWorld.

etc. Lecturer in Computer Science. The interface objects seen by the user are the same from system to system: push buttons. and it goes a long way towards organizing and removing window clutter. 8. Individual windows can be iconified or expanded as desired within the MDI frame. each containing a document. KCCS Warangal . and its own dialog boxes. Static text labels Push buttons List boxes Combo boxes (a more advanced form of list) Radio boxes Check boxes Editable text areas (single and multi-line) Scroll bars You can create these controls either in code or through a "resource editor" that can create dialogs and the controls inside of them. or SDI. along with its resource editors. 3. 4." By R. pull down menus. each of which contains controls. objects and such that are manipulated with the mouse or the keyboard. When implemented with MDI. makes the creation and customization of these interface objects extremely easy. 5. These interface objects all work the same way. PIF editor. although some have minor differences in their "look and feel. 6. or MDI for more complicated applications. Windows applications use several standard user controls: 1.0) Windows Vocabulary The vocabulary used to talk about user interface features and software development in Windows is basic but unique. Visual C++. its own menu structure. The Clock. 7. Thirupathi MCA. 2. On screen the user sees a group of windows. Most simple Windows applications use a Single Document Interface. Each application that you create will use its own unique set of controls.34 - .. The single main menu is held by the main application window and it applies to the top-most window held within the MDI frame. scroll bars. Windows also provides an organizing scheme called the Multiple Document Interface. icons. Event-driven Software and Vocabulary All window-based GUIs contain the same basic elements and all operate in the same way. A great deal of the effort that goes into creating any good application interface lies in the choice and organization of these interface objects. the application presents a large application window that can hold multiple sub-windows. The MDI interface gives the impression of a second desktop out on the desktop. frame. dialog boxes.WEB AND VISUAL PROGRAMMING (VC++ 6. icons. The MDI system allows the user to view multiple documents at the same time within a single instance of an application. and Notepad are examples of SDI applications. or the entire MDI frame can be minimized into a single icon on the desktop.

Click on the ClassView tab and expand the "hello classes" tree and you will see the classes in the application. but there is now also a ClassView and a FileView tab. and so on. If you want to change the colors or turn the coloring off. This subdirectory holds all disposable (easily recreated) files generated by the compiler.NCB. highlight Win32 Application. click the FileView tab and expand the tree on the icon labeled "hello files".CPP in the new directory Visual C++ created. Save it to a file named HELLO. In the File menu select the New option to create a new editor window. By R. The ClassView tab will show you a list of all of the classes in your application and the FileView tab gives you a list of all of the files in the project. In the dialog that appears.OPT. Under the Projects tab. After you have finished entering the code.CPP. In the Location field type an appropriate path name or click the Browse button. HELLO. and you will see that word echoed in the Location field as well.DSP. and you will use it to enter the program shown above. Click the OK button. Notice there is an option for the typical "Hello World" application. Make sure the "Add to Project" option is checked for Project "hello". click "Finish". use the default selection "An empty project". then expand the tree on the folder icon labeled "Source Files". In the next window. save the file by selecting the Save option in the File menu. In the area on the left side of the screen. string literals. double-click on HELLO. You will see the file named HELLO. clicking the file. choose the Build HELLO.DSW in that directory. KCCS Warangal . If there is some aspect of the editor that displeases you. make sure the Files tab is active and request a "C++ Source File".WEB AND VISUAL PROGRAMMING (VC++ 6. Type the word "hello" in for the project name. and HELLO. Visual C++ will create a new subdirectory named Debug and place the executable named HELLO. In this case. Thirupathi MCA. Now it is time to type in the code for the program..EXE option in the Build menu to compile and link the code.EXE in that new subdirectory.CPP. You can remove a file from a project at any time by going to the FileView. HELLO. Visual C++ will create a new subdirectory named HELLO and place the project files named HELLO. Type (copy/paste) the code in the listing into the editor window. If you quit and later want to reopen the project.0) Creating a Project and Compiling the Code To create a new project for HELLO. you may be able to change it using the Editor tab of the Options dialog. The InfoView tab is still there. choose the New option in the File menu. You will find that the editor automatically colors different pieces of text such as comments. Lecturer in Computer Science. however it skips a few important steps you are about to take. go to the Options option in the Tools menu. key words. then click "OK" once more in the next window. and pressing the delete button. Visual C++ comes with its own intelligent C++ editor. The area along the left side of the screen will now change so that three tabs are available. and enter "hello" for "File name".35 - . choose the Format tab and select the Source Windows option from the left hand list.DSW.

Debugging as a Development Consideration The Different types of Programming errors Syntax. To execute the program. Changing Values Introducing the various Debug Windows and Their Uses The The The The The The Variables Window Watch Window Registers Window Memory Window Call Stack Window Disassembly Window 1. Runtime Components of a Useful debugger Resolving program code mistakes is known as Debugging. Lecturer in Computer Science. A Debugger should have at least 4 capabilities 1. A window appears with the words "hello world".. Symantec. Thirupathi MCA. 2. Break Points 3.0) so you can delete this directory when you run short on disk space without fear of losing anything important. Inside the window is a static label displaying the words "hello world". Tracing. Compare your code against the code above and fix the problem. KCCS Warangal . The Variables Window The variables window presents a look at variables that have definition within the current function. If you see compiler errors. simply double click on the error message in the output window. choose the Execute HELLO. The editor will take you to that error. You may want to simply delete your new directory and recreate it again following the instructions given above exactly. The window itself has the usual decorations: a title bar. it probably means that you specified the project type incorrectly in the dialog used to create the project.WEB AND VISUAL PROGRAMMING (VC++ 6. and so on. minimize and maximize buttons. Note that the program is complete.EXE option in the Build menu. If you see a mass of linker errors.36 - . Watching Variables 4. re-size areas. The window has three panels: By R.

including its floating-point registers. Registers are storage locations built into the computer’s processor storage locations that.37 - . You can use the keyboard to enter an expression within the watch window’s Name field..It shows the object to which the this pointer currently points. The Watch Window It is used to monitor the values of expressions. word format. 4. including both locally defined variables and function parameters. Lecturer in Computer Science. and double word format) in the address space of the process that you are debugging. The Registers Window It shows the current values of the registers in the computer’s processor. It uses a different color to mark expressions whose values change as you single-step through your code. KCCS Warangal .It displays variables that are declared locally within the current procedure. Watch window has four panels. This Panel:. The Memory Window It shows the memory contents (in byte format. Thirupathi MCA.It shows all variables that have local definition within the current function. By R. 3. Local Panel:. 2.0) Auto Panel:.WEB AND VISUAL PROGRAMMING (VC++ 6. typically can store small integers.

6.WEB AND VISUAL PROGRAMMING (VC++ 6. Lecturer in Computer Science. the debugger will update source windows and other debug windows to reflect the context of the function you select.0) 5. The Disassembly Window It provides a view of the assembly language code that the compiler generates when it compiles your application. Thirupathi MCA.38 - .. By R. KCCS Warangal . If you double-click a function within the call stack window. The Call Stack Window It lists the hierarchy of functions calls that led to the current function the application is executing.

MFC Base Classes There are two main base classes in MFC: 1.. cFrameWnd cWinApp class: This is the base class from which a windows application object is derived. The outputs of both the compilers (code and resource) are linked together and the final executable file is obtained. Code compilation 2. Run(): This method acquires tand dispatches windows calls until the application receives the WM_QUIT (a constant). we can create Windows dialog boxes.39 - . bitmaps etc compiled separately and a RES file is obtained. Resource compilation: Resource files like images. KCCS Warangal . 2.0) INTRODUCTION TO MFC USING CALLBACK FUNCTIONS AND MESSAGE LOOP Overview of MFC MFC class library is an application framework for writing applications for Windows platform or any other platform that supports Win32 APIs It is a collection of C++ classes or in other words MFC is an encapsulation of large portion of Windows API in C++ form Using MFCs. message. icons. ExitInstance(): It is called when an application object is removed from the memory By R. (ie. cWinApp class provides3 methods: 1. An application object consists of member functions for initializing applications.WEB AND VISUAL PROGRAMMING (VC++ 6. Lecturer in Computer Science. InitInstance(): This method is called when the application object is loaded into the memory. device context and other common graphic objects Classes provided by MFCs are accessed through interfaces. when “X” button is pressed) 3. Thirupathi MCA. Execution of MFC There are two steps of execution: 1. cWinApp 2. Resource compilation Code compilation: The source code is compiled along with the required libraries (windows headers and runtime header files) and an object file is created. MFC code is compiled and converted into Win32 API calls.

MyWindow mywinobj. } ~MyWindow() { messageBox(“Sample window”.40 - . class MyApp : Public cWinApp { Public: // Override these methods BOOL InitInstance(). “cFrameWnd”). } BOOL MyApp :: InitInstance() { :: messageBox(o. “InitInstance”. } }. return TRUE. Mywinobj->showwindow(SW_SHOWMAXIMIZED). BOOL ExitInstance().WEB AND VISUAL PROGRAMMING (VC++ 6. Lecturer in Computer Science. // Speicify the main window M_PMainWnd = mywinobj.0) A sample program to create a frame and display a message box when InitInstance() is invoked #include<afxwin. “Sample window”). “Sample Window”. } By R.. Mywinobj = new MyWindow. Thirupathi MCA. MB_OK | MB_ICONASTERIX).h> class MyWindow : Public cFrameWnd { Public: MyWindow() { // NULL is for icon create(NULL. KCCS Warangal .

. When the dialog has the OK and the Cancel buttons. change the file as follows: #include <afxwin. BOOL CExerciseApp::InitInstance() 1.. or application. Set the File Name to Exercise and click Finish. The user is usually not allowed to continue any other operation until the dialog box is dismissed. maximized. 4.h> class CExerciseApp : public CWinApp { public: BOOL InitInstance(). on the main menu. Lecturer in Computer Science. Thirupathi MCA. In the Templates section. 6. window. 2. right-click ExoDialog1 and click Properties. 8. specify that you want to Use MFC in a Shared DLL To create the application class of the project. In the Property Pages. Most dialog boxes have the OK and the Cancel buttons. The controls it hosts accomplish the role of dialog between the user and the machine.. the OK button is configured to behave as if the user had pressed Enter. click Project > Add New Item. whatever the user had done would be acknowledged and transferred to the hosting dialog box. click C++ File. }. this button allows the user to dismiss the dialog and ignore whatever the user would have done on the dialog box. KCCS Warangal . • • • Creating an Application Start Microsoft Visual C++ or Microsoft Visual Studio Create a new Win32 Project named ExoDialog1 Make sure you create the Windows Application in an Empty Project In the Solution Explorer. It cannot be minimized. 3. For this reason. As the only system button. It is usually modal. 5. In that case.. 7. although this depends on the application developer.. To create the application. A dialog box does not have any other system button but Close.0) CALLBACK FUNCTIONS AND MESSAGE LOOP Creating and using dialog boxes Overview of Dialog Boxes A dialog box is a rectangular window whose main role is to host or hold other Windows controls. a dialog box means nothing. It is the primary interface of user interaction with the computer.WEB AND VISUAL PROGRAMMING (VC++ 6. or restored. Pressing Esc applies the same behavior as if the user had clicked Cancel. It provides a way for the user to close or dismiss the dialog.41 - . a dialog box is referred to as a container. A dialog box has the following characteristics: • It is equipped with the system Close button . By itself. By R.

on the Standard toolbar. 2. behind the scenes. on the main menu.h" By R. In the Add Resource dialog box. Lecturer in Computer Science.rc as we saw in a previous lesson. After creating a "physical" dialog box. Creating a Dialog Box 1. 9. } CExerciseApp theApp. it creates the appropriate section for a dialog box. Microsoft Visual C++ makes it particularly easy to create a dialog box and. click the Save All button 4.h> #include "Resource. you should create its class so that other objects of the application can use this control. Save All Dialog Box Creation When using Win32 to create an application.WEB AND VISUAL PROGRAMMING (VC++ 6. To create a dialog box. from the Add Resources dialog box. simply select the Dialog node and the object is ready. To create a class for the dialog box and display the dialog box in the application. KCCS Warangal ...0) { return TRUE. To save the dialog box and the new resource. To create a dialog box in MSVC.42 - . a dialog is created using a text file called a resource file. change the file as follows: #include <afxwin. The file has the extension . Thirupathi MCA.. click Project -> Add Resource. click Dialog and click New 3.

WEB AND VISUAL PROGRAMMING (VC++ 6. Close it and return to MSVC Handling Dialog Boxes in MFC Dialog boxes in MFC usually are based on dialog box templates. DLGTEMPLATEEX. } CExerciseApp theApp. You can fill these structures with positioning information. Dlg. Lecturer in Computer Science. ID.. user interface software would progress at a snail's pace. Fortunately. Thirupathi MCA. NULL) { } BOOL CExerciseApp::InitInstance() { CExoDialog Dlg. }. and style flags required to describe every control on a dialog box. After you create a dialog box template resource. return TRUE. and DLGITEMTEMPLATEEX. These dialog box templates are binary resources held in the structure defined by the Win32 DLGTEMPLATE. the Visual Studio dialog box Template Editor is a powerful tool dedicated to this task. class CExoDialog : public CDialog { public: enum { IDD = IDD_DIALOG1 }.DoModal(). CExoDialog(). If these structures were created tediously by hand for every dialog box. 5. size. DLGITEMTEMPLATE. }. By R. CExoDialog::CExoDialog() : CDialog(CExoDialog::IDD. Test the application 6. you can create a CDialogderived class that uses the template to create the dialog box and then manages the exchange between window controls and your dialog box's member variables.0) class CExerciseApp : public CWinApp { public: BOOL InitInstance(). KCCS Warangal .43 - . m_pMainWnd = &Dlg.

44. 0.WS_BORDER | WS_TABSTOP.97.42. KCCS Warangal . Visual Studio saves the details in a text format in your project's .7.7.res extension that holds the binary format of these dialog box templates (and the other By R.14 PUSHBUTTON "Cancel". Lecturer in Computer Science.0) Creating Dialog Box Template Resources You can create dialog boxes and add controls by using the Resource Editor.7. 135 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Custom Dialog" FONT 8..53.IDC_TREE1.IDOK.175. Editing a dialog box with Visual Studio's Dialog Box Editor.7.50.15 CONTROL "Tree1". such as this entry produced for the dialog box shown IDD_CUSTOM_DIALOG DIALOG DISCARDABLE 0.42.14. It is interesting to note the code produced after editing a dialog box. 232.WEB AND VISUAL PROGRAMMING (VC++ 6."SysDateTimePick32".ES_AUTOHSCROLL LISTBOX IDC_LIST1.14 LTEXT "Static Text".50.IDC_STATIC.IDCANCEL. because the Resource Editor should solely maintain it. Thirupathi MCA. After you create the dialog box. as shows."SysTreeView32".23. however.LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP CONTROL "DateTimePicker1".rc file directly.146. 161.175.64.IDC_DATETIMEPICKER1. "MS Sans Serif" BEGIN DEFPUSHBUTTON "OK".rc file.86 END When you compile the resources. These details provide the source code required for the Resource Compiler to generate the required DLGTEMPLATE and DLGITEMTEMPLATE binary structures. EDITTEXT IDC_EDIT1. DTS_RIGHTALIGN | WS_TABSTOP.19.64.44 - . You'll rarely need to edit the . the compiler produces a file with a .

You could create the derived class by hand. the wizard displays the New Class dialog box.dll. but the wizard makes this process much easier.res file then is linked with the program code (. but you sometimes may want to select an existing implementation. Creating a CDialog-Derived Class You can use ClassWizard to generate a CDialog-derived class by invoking the wizard while the new dialog box is displayed in the Resource Editor.exe.. Thirupathi MCA.45 - . Lecturer in Computer Science. Normally. By R. ClassWizard detects that there is no class currently held in the . or . as The New Class dialog box. you would create a new dialog box handler class.obj files) to produce your target .lib file.clw file that uses the ID of the new dialog box template resource. It then displays a dialog box to let you select an existing handler class or create a new one ClassWizard prompts you to create or select a dialog box handler class. If you choose to create a new dialog box handler class.0) resources).WEB AND VISUAL PROGRAMMING (VC++ 6. KCCS Warangal . . This .

comments created by ClassWizard.46 - . The default implementation of CDialog calls EndDialog() in response to the user clicking the OK or Cancel button. If your application is object linking and embedding (OLE)-enabled. Lecturer in Computer Science. This is because the dialog box is a window. You can change these autogenerated filenames if they aren't appropriate. After you click OK in the New Class dialog box. it adds the new code inside the appropriate comment sections. you'll see that it passes this ID down to the CDialog base class. and a message map declaration: DECLARE_MESSAGE_MAP() All classes that implement the DECLARE_MESSAGE_MAP macro must be derived from the CCmdTarget class. When a modal dialog box is displayed. You'll also notice that the dialog box ID is enumerated as the IDD member with a value based on your dialog box template's resource ID. The CDialog base class and your dialog box template ID are selected automatically. Displaying the Dialog Box Dialog boxes normally are displayed in a modal sense. users are unable to interact with any other part of the application until they click OK or Cancel to exit the dialog box..WEB AND VISUAL PROGRAMMING (VC++ 6. and your CDialog-derived class must process messages from its own window and the various dialog box controls (which are child windows). If you examine the dialog constructor function. Thirupathi MCA. you also can specify any OLE automation specific details for the new dialog box. If you examine the new header.0) The New Class dialog box lets you change the name of the class. The dialog box class definition also includes a declaration for the DoDataExchange() virtual function (covered in more detail later in the section.. you see the new dialog box handler class in the ClassView pane.. By R. The CDialog class's DoModal() function initiates the modal process and ends when the EndDialog() member function is called. KCCS Warangal . such as this: enum {IDD = IDD_CUSTOM_DIALOG }. along with an optional parent-window pointer: CCustomDlg::CCustomDlg(CWnd* pParent /*=NULL*/) : CDialog(CCustomDlg::IDD. "The Data Exchange and Validation Mechanism"). When you subsequently add member variables and functions with ClassWizard. It then generates filenames based on the name you have specified. you see a minefield of //{{AFX_. pParent) { //{{AFX_DATA_INIT(CCustomDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT } The //{{AFX_DATA_INIT section in the constructor implementation is used by ClassWizard to initialize any member variables that you insert using the wizard. The dialog box class is derived from CCmdTarget through the CWnd class.

or an HGLOBAL handle to a global memory segment. The corresponding ScreenToClient() function performs the opposite conversion. Dialog Box Coordinates When you edit a dialog box in the Resource Editor. This integer actually is returned from the parameter passed to EndDialog(). ClientToScreen() converts client coordinates held in a RECT or POINT structure into screen coordinates. Most dialog boxes use the default system font. If you do want to use a dialog box template constructed in memory. Changing the Input Focus and Default Buttons When you edit a dialog box template in the Resource Editor. Dialog boxes use their own coordinate system based on the size of the font being used in the dialog box. but you can set different fonts when editing the dialog box.47 - . The following lines show how an object of the CCustomDlg class is constructed and displayed. Whenever the user presses the Tab button while the dialog box is displayed. MapDialogRect() then translates these dialog box coordinates into screen coordinates. You then can call DoModal() as normal to display the modal dialog box. If the initialization succeeds. you should construct a CDialog-derived class calling the constructor with no parameters.WEB AND VISUAL PROGRAMMING (VC++ 6. the control positions and sizes are converted from dialog box units to real-screen units. you can set the tab order by pressing Ctrl+D. By R.0) You can use the integer value returned from DoModal() to find out which button was pressed. Lecturer in Computer Science. you'll notice that the coordinates don't correspond to the current screen resolution. as well as how the return code determines which button was clicked to close the dialog box: CCustomDlg dlgCustom. Thirupathi MCA. else AfxMessageBox("User Hit Cancel"). You can convert between these dialog box units and the real-screen coordinates by passing a RECT structure holding the dialog box coordinates to the MapDialogRect()function. the input focus moves to the next control in this tab order.. You may find the CWnd base class's ClientToScreen() function useful when manipulating screen coordinates relative to the dialog box. which by default is IDOK or IDCANCEL in response to the OK or Cancel button.DoModal()==IDOK) AfxMessageBox("User Hit OK"). Then you can call the InitModalIndirect() function passing a pointer to a DLGTEMPLATE structure in memory. depending on the size of the font used. InitModalIndirect() returns a TRUE value. if (dlgCustom. When the dialog box is displayed. from within your code by calling the CWnd base class's SetFont() function. or by overriding the CDialog class's OnSetFont() function and supplying a pointer to your required dialog box font. KCCS Warangal .

Mapping Member Variables to Controls You can use ClassWizard to add member variables and provide the mapping for most of the dialog box controls via ClassWizard's Member Variables tab The ClassWizard Member Variables tab. KCCS Warangal . you could call the following from within your dialog box class (after activation): GotoDlgCtrl(GetDlgItem(IDOK)). You can set the focus to a specific control after the dialog box is displayed by calling GotoDlgCtrl() and passing a pointer to the control's window. and then save that data back into those variables. Lecturer in Computer Science.48 - . You'll probably also want to validate the values stored in the controls to ensure that they are within acceptable ranges when the user attempts to click OK to exit the dialog box.0) A set of member CDialog functions lets you change the current input focus from within your code based on this tab order. You can set the context help ID for a dialog box by calling SetHelpID(). Normally the OK button is the default button. To set the input focus to the OK button. You can find this pointer by ID by calling GetDlgItem(). You can change this behavior by passing a different button ID to SetDefID().WEB AND VISUAL PROGRAMMING (VC++ 6. Thirupathi MCA. Dialog Box Data Exchange and Validation The controls in a dialog box are specialized windows that store their own copy of the data that the user enters or changes. In the lifetime of a dialog box. The Member Variables tab lists the control IDs of the various controls. You can select an ID and click the Add Variable button to display the Add Member Variable dialog box By R.. so when a user presses the Enter key. the OK button is clicked. you'll normally want to initialize these controls with data from your program. The corresponding GetDefID() returns the ID of the current default button. for example. The NextDlgCtrl() and PrevDlgCtrl() functions let you move forward and backward through the tab order.

but often you'll need to map a control class to the control so that you can manipulate the control's more advanced features. you'll notice that the new member variable is inserted into your dialog box handler class definition between the ClassWizard AFX_DATA-generated comments. You can map a number of variables to the same control so that you can perform easy value transfer and allow control handler class mapping concurrently.WEB AND VISUAL PROGRAMMING (VC++ 6. KCCS Warangal . If you set the Category combo box to indicate value mapping. //}}AFX_DATA_MAP } By R. The variable types available change depending on your selection in the Category combo box. The new variable also initializes your dialog box class's constructor function like this: //{{AFX_DATA_INIT(CCustomDlg) m_strCustomEdit = _T(""). as well as a variable type. m_strCustomEdit).. //{{AFX_DATA_MAP(CCustomDlg) DDX_Text(pDX. Lecturer in Computer Science. //}}AFX_DATA_INIT You'll see a new entry placed in the DoDataExchange() function like this: void CCustomDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX).49 - . IDC_CUSTOM_EDIT. These values are great for quick and easy value-oriented transfer. You'll notice that the Add Member Variable dialog box lets you set a category that can be a value or a control. Thirupathi MCA.0) The Add Member Variable dialog box. After you add the member variable map. the Variable Type combo box lists member variable types that can be used with the type of control being mapped.

If you map a CString to an Edit control. If you were to add a control map for the edit control. Consider this example: DDX_Control(pDX. long double. DWORD. Some Common Controls and Their Mapping Classes/Variables Allowable Mapped Data Types CString CString. If you set any of these validation rules. you'll see different DDX_ macros used to map the various types of controls to various data types. m_editCustom).. int Extended Combo CComboBoxEx CString. KCCS Warangal . IDC_CUSTOM_EDIT. If you insert other variable types.0) The new DDX_Text macro entry automates data transfer between the control identified by IDC_CUSTOM_EDIT and your m_strCustomEdit member variable.1 lists some of these controls. int ComboBox CComboBox CString. like this: Mapping Class CStatic CEdit By R. Lecturer in Computer Science. float. ClassWizard adds DDV_ routines to the DoDataExchange() function to perform validation. for example. Depending on the variable type mapped. short COleDateTime & ColeCurrency Button CButton None CheckBox CButton BOOL int 3-State CheckBox CButton Radio CButton int ListBox CListBox CString. such as Edit controls. and a corresponding DDX_Control macro to map it to the control ID. Table 5.50 - . BOOL. int. you can set upper and lower ranges for the entered value. you'd see a CEdit member variable entry added to the class definition. If you map an integer to the Edit control. COleDateTime Control Static Edit You can add some simple validation maps to certain controls. int ScrollBar CScrollBar int Spin CSpinButtonCtrl None Progress Bar CProgressCtrl None Slider Control CSliderCtrl int List Control CListCtrl None Tree Control CTreeCtrl None Date Time Picker CDateTimeCtrl CTime. UINT. COleDateTime Month Calendar CMonthCalCtrl CTime. Thirupathi MCA. the lower section of the Member Variables tab displays a section that lets you specify validation information.WEB AND VISUAL PROGRAMMING (VC++ 6. you can set the validation rules to limit the maximum number of characters allowed in the Edit control.

The default OnInitDialog() implementation initializes the controls to their initial settings from the member variables. Thirupathi MCA. member variables. and control types. Finally. the data from the controls is validated using DDV_ routines and then transferred back into the member variables using the DDX_ routines again. m_strCustomEdit. This object holds the details that let the DDX routines know whether they should be transferring data to or from the controls. Lecturer in Computer Science. // return TRUE unless you set the focus to a control By R. this function subclasses any mapped controls through the DDX_Control routine. // TODO: Add extra initialization here return TRUE. It is set to FALSE when data from the member variables should be loaded into the controls. This message tells the dialog box handler class that the dialog box and controls have been created but require initialization. Initializing the Dialog Box Controls Obviously.0) DDV_MaxChars(pDX. 10). your CDialog-derived class gains an OnInitDialog() function that looks like this: BOOL CCustomDlg::OnInitDialog() { CDialog::OnInitDialog(). the DoDataExchange() function must be called initially to load the default values from the mapped member variables into the controls. When the dialog box is initialized. The Data Exchange and Validation Mechanism The DoDataExchange() function is called several times during the lifetime of a dialog box and performs a variety of tasks. This initialization can't be performed until the dialog box is open. after the user clicks OK. You can add your own custom code to DoDataExchange() to transfer data to or from the controls and check the m_bSaveAndValidate member of the CDataExchange object to see whether you should be transferring the data to or from the control. When the m_bSaveAndValidate member is set to TRUE. Several different DDV_ routines exist for the various types of validation rules. the data exchange should transfer data from the controls to the member variables and perform validation. But the first message it receives before the box actually is displayed is a WM_INITDIALOG. because the controls don't exist yet.WEB AND VISUAL PROGRAMMING (VC++ 6. After the DoModal() function is entered and the dialog box is created. When you add a handler for the WM_INITDIALOG message through the Add New Windows Message/Event Handler dialog box.. it enters a message loop to wait for interaction from the user. Then it transfers the data held in the member variables to the controls using the DDX_ routines. The DDX_ routines then implement the Windows message required to set or retrieve data from the control associated with the given control ID.51 - . KCCS Warangal .

WEB AND VISUAL PROGRAMMING (VC++ 6. DDX_Control(pDX. You can disable some of the dialog box controls by passing FALSE to the EnableWindow() function of any of the control mapping classes like this: m_editCustom. UpdateData() often is useful when you are responding to messages from one control (such as a combo box) but want to use the result from that control to update another.. Lecturer in Computer Science. CListBox. Thirupathi MCA. passing a TRUE value for the m_bSaveAndValidate flag.EnableWindow(FALSE).0) // EXCEPTION: OCX Property Pages should return FALSE } You'll notice that OnInitDialog() first calls the base class implementation to initialize the controls. m_listCustom. and so on). ClassWizard creates DDX_Control maps to initialize the control mapping variables. ClassWizard generates code to map the m_listCustom and m_editCustom variables to the edit and list box controls in the dialog box. to retrieve the current contents of an Edit control: CString strText. Windows sets the input focus to the first control in the dialog box (as defined by the tab order). CComboBox. m_editCustom). UpdateData() returns a TRUE value if the validation succeeded or FALSE if there was a problem validating the data. m_editCustom. IDC_CUSTOM_LIST. m_listCustom). You also can set the text by using the SetWindowText() function. You'll also notice that OnInitDialog() must return a Boolean value. The following lines use a CEdit control mapped object (m_editCustom). You then can add lines to perform your own specialized initialization. such as list or tree controls like this list control initialization (where m_listCustom is a CListBox object): m_listCustom. you may want to initialize more sophisticated controls. If you return TRUE. Each of the control mapping classes has a large range of member functions to exchange and manipulate specific aspects of the control. Alternatively. Once again. DoDataExchange() is called from UpdateData()— this time.GetWindowText(strText).AddString("Goodbye"). You can perform more precise data transfers by using the control mapping classes (such as CEdit. m_listCustom. for example. If you return FALSE. you must set the input focus to a specific control yourself from within OnInitDialog(). All these mapping classes are derived from CWnd. For the examples shown above. IDC_CUSTOM_EDIT.AddString("World"). Retrieving Data from the Controls You can call UpdateData() passing TRUE to retrieve and validate the current data from the controls. KCCS Warangal .52 - . like this: DDX_Control(pDX. By R.AddString("Cruel").

you may want to disable the Edit control if the first item in a list box is selected. CDialog) //{{AFX_MSG_MAP(CCustomDlg) ON_LBN_SELCHANGE(IDC_CUSTOM_LIST. a message handler function is generated in your dialog box class along with a message map macro specific to the type of message selected. The Message Maps tab. Your implementation then can directly manipulate other controls through their control mapping objects. such as changing the selection in a list box.WEB AND VISUAL PROGRAMMING (VC++ 6. You can select the ID associated with the required control to display the notification messages available from that control. You can use the Message Maps tab in ClassWizard to insert the message map entries for these notifications.0) Responding to Control Notifications These messages are sent from the control to the parent dialog box after the user performs a specific action. OnSelchangeCustomList) //}}AFX_MSG_MAP END_MESSAGE_MAP() When you click on a valid list box line. but enable it otherwise with a notification handler function like this: void CCustomDlg::OnSelchangeCustomList() { By R. For example. This message map entry then calls your OnSelchangeCustomList() implementation.53 - . KCCS Warangal . For example. Thirupathi MCA. When you add the new message handler. a list box selection changed notification results in the following message map entry: BEGIN_MESSAGE_MAP(CCustomDlg. You then can add handler functions for these notifications by clicking Add Function. the control posts the LBN_SELCHANGE notification to the parent dialog box.. Lecturer in Computer Science.

EnableWindow(bEnable).WEB AND VISUAL PROGRAMMING (VC++ 6. and then call any of the control map member functions to send messages that manipulate the control. Responding to OK and Cancel When you click OK or Cancel. The default implementation for OnCancel() is fairly simple and just calls EndDialog() passing IDCANCEL. To change the text and disable the OK button using a dynamic map. You can call EndDialog() at any time during a modal dialog box's lifetime to close the dialog box. which you should check.0) BOOL bEnable = (m_listCustom. } If you don't add specific handlers for these messages. pOK->EnableWindow(FALSE). You can map any of the control mapping classes to their corresponding controls in this way. GetDlgItem() returns a NULL value. the framework normally calls CDialog's OnOK() and OnCancel() virtual functions. You can create a local temporary map to a specific control. EndDialog() is called and passed IDOK to close the dialog box.. You can add your own BN_CLICKED handler function for the OK and Cancel buttons to perform specialized validation. you might add the following code in response to a control notification message: CButton* pOK = (CButton*)GetDlgItem(IDOK). otherwise. } If the control ID can't be found. the dialog box remains open. for example. Otherwise.54 - . if (pOK) { pOK->SetWindowText("Not OK"). you risk a crash caused by calling through a NULL pointer. Thirupathi MCA. If the validation fails. Dynamically Mapping Controls Instead of using ClassWizard to generate member variable control mapping objects and their associated DDX_ routine entries. KCCS Warangal . they will be passed down to the CDialog base class (and then the CWnd class) to be handled by the dialog box's default implementations. Then you might perform your own special OnOK() code before calling EndDialog() to close the dialog box. The default implementation for OnOk() calls UpdateData(TRUE) to save and validate the information from the dialog box controls.GetCurSel()==0). by using the GetDlgItem() function and casting the CWnd pointer returned to the specific control mapping class. By R. m_editCustom. This closes the dialog box and returns IDCANCEL from the DoModal() function. The corresponding GetDlgCtrlID() function returns the ID associated with any particular control. Lecturer in Computer Science.

Deriving your own control class. you can derive it from CWnd directly and write a new control from scratch. a new control class appears in your ClassView. Thirupathi MCA. This technique can let you subtly (or drastically) modify the behavior of the standard Windows controls.55 - . After you click OK. After entering a name for your new control class. Creating a Derived Control You can use ClassWizard to create a new class derived from an existing MFC control class by clicking the Add Class button and selecting New to display the New Class dialog box. Many third-party software vendors supply libraries full of these extended classes to greatly enhance the control capabilities. You could create a custom Edit control that converts uppercase letters to lowercase letters. for example. KCCS Warangal . you can set the base class to one of the existing MFC control classes. as shown. You could add a handler to catch the WM_CHAR messages and change any uppercase characters to lowercase. Lecturer in Computer Science. Instead of deriving your custom control from another MFC control class.0) Derived Control Classes in Dialog Boxes You can extend the functional ity of any of the standard control classes by deriving your own classes and then use these extended controls in your dialog box.WEB AND VISUAL PROGRAMMING (VC++ 6. Customizing the Derived Control You change or extend the default functionality of your new derived class by adding message-handler functions to intercept the Windows messages before they are passed to the base class. like this: By R.. This new class just consists of constructor/destructor functions and a message map derived from the existing MFC class.

// Make it lowercase DefWindowProc(WM_CHAR. Lecturer in Computer Science. Mapping your derived class to a dialog box control.nFlags)). CEdit) //{{AFX_MSG_MAP(CCustomEdit) ON_WM_CHAR() //}}AFX_MSG_MAP END_MESSAGE_MAP() This macro is responsible for separating the nRepCnt and nFlags word values from the original LPARAM parameter sent in the WM_CHAR message. The MAKELONG macro merely recombines these values back into a single LPARAM parameter for the DefWindowProc() function. By R. UINT nRepCnt. } Instead of calling the base class CEdit::OnChar() function. the preceding example calls DefWindowProc().nChar. UINT nFlags) { if (nChar>='A' && nChar<='Z') nChar+=32.56 - . Thirupathi MCA. like this: BEGIN_MESSAGE_MAP(CCustomEdit. Using the Derived Control in a Dialog Box After you derive a custom control.0) void CCustomEdit::OnChar(UINT nChar. you can use it in a dialog box as a mapped member variable (as you would any standard MFC control). directly passing the modified nChar variable.. you'll find that your new class is available from the list of control variable types in the Add Member Variable dialog box. KCCS Warangal .MAKELONG(nRepCnt. You'll notice that a corresponding ON_WM_CHAR message-handler macro was added to your derived control's message map. If you used ClassWizard to create the derived control class.WEB AND VISUAL PROGRAMMING (VC++ 6.

for ex ample. you'll notice that ClassWizard adds the new member variable to the dialog box's class definition as normal: CCustomEdit m_ceditCustomEdit..this). for example. m_ceditCustomEdit. ClassWizard prompts you with a message box to remind you that you must manually add an #include for the custom control's class definition before the new member variable declaration. If your new derived class is defined in the CustomEdit. the behavior of your new customized control is changed accordingly. You may want to display a dialog box like a control palette. because these usually are associated with modal operations. You must do this because By R. Thirupathi MCA. The user normally closes a modeless dialog box via the close box (a small x). To do this.h" You now should find that when your new dialog box is displayed. return TRUE. The term subclassing in this circumstance is different from the object-oriented subclass term and really means use this class to handle the Windows messages for this control.57 - .0) After clicking OK to map the new member variable to your derived class. the user is unable to interact with any other parts of the application's user interface until the dialog box is closed. This subclassing normally is performed during the first pass of DoDataExchange() from inside a DDX_Control() routine. or to provide feedback such as coordinates from a drawing operation. To manually subclass the new custom edit box (m_ceditCustomEdit). You must pass the control ID and a valid parent dialog box pointer to SubclassDlgItem(). Modeless Dialog Box Resource Templates You may not require OK and Cancel buttons for a modeless dialog box. } Modeless Dialog Boxes When a modal dialog box is displayed. you should add the #include before your custom dialog box definition: #include "CustomEdit. your OnInitDialog() function may look like this: BOOL CCustomDlg::OnInitDialog() { CDialog::OnInitDialog().h module. for example. you'll need a modeless dialog box. Lecturer in Computer Science. you must override the default OnOK() and OnCancel() message handlers and create your own that call DestroyWindow(). If you do decide to use OK and Cancel buttons. KCCS Warangal .SubclassDlgItem(IDC_CUSTOM_EDIT.WEB AND VISUAL PROGRAMMING (VC++ 6.

WEB AND VISUAL PROGRAMMING (VC++ 6. You should pass the dialog box's template ID (or a resource name) to Create() and optionally a pointer to a parent window. If you don't track the dialog box. It shows the Visible property for a modeless dialog box with no OK or Cancel button.. A typical modeless dialog box template and properties. when the function returns. The dialog box is created but remains invisible unless you call the dialog box's ShowWindow() function passing TRUE. You should set the Visible flag in the dialog box's properties (on the More Styles tab) to visible the dialog box. and the modeless dialog box is destroyed immediately by the CDialog base class destructor. for example. If you do. pDlgModeless->Create(CModeless::IDD). Creating and Destroying Modeless Dialog Boxes You can create a modeless dialog box by using the Create() function instead of the DoModal() function to display the dialog box.58 - .0) the default functions call EndDialog(). KCCS Warangal . The Create() function returns immediately after the dialog box is created—unlike the DoModal(). Create() returns a TRUE value and the dialog box is created. which only closes a dialog box in modal operation. Lecturer in Computer Science. you may create an instance from a menu handler function like this: void CDialogTemplDoc::OnShowdialogDisplaymodeless() { CModeless* pDlgModeless = new CModeless. If the creation succeeds. Thirupathi MCA. This has implications for the scope and lifetime of your modeless dialog box class. You should never declare your modeless dialog box as a local function variable as you might with a modal dialog box. } By R. the dialog box's handler object is destroyed.

} By R. } void CModeless::PostNcDestroy() { CDialog::PostNcDestroy(). // Delete Ourselves delete this. delete this. } Tracking Modeless Dialog Boxes The memory-tracking technique is very simplistic and allows the user to create many instances of the modeless dialog box.WEB AND VISUAL PROGRAMMING (VC++ 6. which probably is undesirable. } The document then can track the modeless dialog box with its own member pointer and close it from a menu handler. KCCS Warangal . and initialize it through the constructor like this: CModeless::CModeless(CDialogTemplDoc* pParent) : m_pParent(pParent) { Create(CModeless::IDD). none of the instances can be destroyed from any objects in your code.. Also. m_pParent->m_pDlgModeless = NULL. Thirupathi MCA.0) You can add an override to your CDialog-derived class by using the Add Virtual Function dialog box and then adding the delete statement like this: void CModeless::PostNcDestroy() { CDialog::PostNcDestroy(). as shown in these lines: CDialogTemplDoc::CDialogTemplDoc() : m_pDlgModeless(NULL) { } void CDialogTemplDoc::OnShowdialogDisplaymodeless() { if (!m_pDlgModeless) m_pDlgModeless = new CModeless(this). You could add a pointer to your CDocument-derived class to the modeless dialog box handler class. for example. } void CDialogTemplDoc::OnShowdialogClosemodeless() { if (m_pDlgModeless) m_pDlgModeless->DestroyWindow().59 - . Lecturer in Computer Science. because the dialog box object is the only thing that knows where its memory is located.

Apply. There are two main modes of operation for property sheets. The only difference is that you should set only the WS_CHILD (the Child setting in the Style combo box) and not the WS_VISIBLE flag (visible from the More Styles tab). Creating and Using property sheets Understanding Property Sheets From a coding perspective. KCCS Warangal .0) This technique also lets you update the controls in the modeless dialog box from other application objects (such as a view to indicate the current mouse position) using dialog box member functions accessible through the document's pointer. This bar lets the modeless dialog box dock naturally to the window frames or float with a small frame. Dialog Bars A dialog bar is a special form of modeless dialog box that encapsulates the functionality of a control bar (like a toolbar or status bar). Thirupathi MCA. although it has a lot in common with a normal CDialog class with a DoModal() function orchestrating By R. You can create a dialog box template for a dialog bar like that for a normal modeless dialog box. Creating a Property Sheet The MFC wrapper classes CPropertySheet and CPropertyPage simplify the process of creating and displaying a property sheet and its pages.WEB AND VISUAL PROGRAMMING (VC++ 6. The CPropertySheet sheet class is derived directly from the CWnd class. You can call its Create() function to create it.60 - . Lecturer in Computer Science. you should think of a property sheet as a collection of individual modeless dialog boxes (representing each page) held inside a larger modal dialog box. You then can construct the dialog bar using the MFC CDialogBar class (inherited from CControlbar) or your own derived class. You can handle the control and messages of a dialog bar as you would a modeless dialog box. Dialog bars let you embed all the normal controls you can use on a dialog box template while letting you dock and reposition the bar like a toolbar. The property sheet itself is implemented down at Win32 level as a dialog box that contains a tab control (one of the common controls) and a set of controlling buttons. The tab control handles the individual dialog boxes that make up the property sheet pages.. Cancel. The dialog bar's Create() function differs from a modeless dialog box's Create() function. such as OK. and Help. Visual C++ 6 introduces support for the new Wizard97 style (only supported on NT 5 and Windows 98). Fortunately the MFC wrapper classes CPropertySheet and CPropertyPage greatly simplify the creation and operation of a property sheet and its property pages.

WEB AND VISUAL PROGRAMMING (VC++ 6. Like dialog boxes. is derived directly from CDialog and acts largely like a modeless dialog box would. Creating this template is usually the first step when building a property sheet. After inserting the property page dialog box template. Creating the Property Page Resources You can use the Resource Editor's Insert Resource dialog box to add a property page specific template by selecting the IDD_PROPPAGE_LARGE. Lecturer in Computer Science. The initial difference from the usual dialog box template that you'll notice is that there are no OK or Cancel buttons. as \ The property page template Style and Border settings. If you examine the Styles tab of the Dialog Properties dialog box for the new template.. KCCS Warangal . Inserting a standard property page dialog box template. you'll notice that Style is set to Child and Border is set to Thin. IDD_PROPPAGE_MEDIUM. By R. these buttons are added automatically to the property sheet and shouldn't exist on the individual pages. because you then can use ClassWizard to automatically create your derived classes based on those templates. used for creating each property page.61 - . However. Thirupathi MCA. By deriving your own classes from these two MFC base classes. the CPropertyPage class. you can resize it as required. each property page needs a dialog box template resource to define the user interface and layout of controls for that page. or IDD_PROPPAGE_SMALL standard option in the Resource Type list. you can extend the specific functionality required for your application.0) the property sheet's modal lifetime.

Each property page must be assigned a unique resource ID. The property page template resource ID and caption. You can add controls to the property page resource template in exactly the same way as you would an ordinary dialog box. because they are each individual dialog boxes in their own right.WEB AND VISUAL PROGRAMMING (VC++ 6. KCCS Warangal .. The property page template Disabled flag. you should set the resource ID and the caption as appropriate to your application.62 - . As with a normal dialog box. You can repeat the same process for each property page you want to include in your property sheet.0) The More Styles tab reveals that the Disabled style also should be set for a property page. Thirupathi MCA. By R. Your property page caption appears on the tab for that specific page when the property sheet is displayed. Lecturer in Computer Science.

WEB AND VISUAL PROGRAMMING (VC++ 6. You must remember to change the Base Class combo box from the default CDialog setting to CPropertyPage. You also can validate that data using the normal DDV macros. You can use ClassWizard to create this class quickly and easily. KCCS Warangal ..63 - . these message map entries By R. You'll notice that the new CPropertyPage-derived class is very similar to a direct CDialog derivation. as shown. Again.0) Creating CPropertyPage-Derived Classes For each property page you want to display. If you decide to create a new class. A message map lets you handle messages from dialog controls and notifications from the parent tab control and property sheet. If you invoke ClassWizard that detects the new resource and offers the option of creating a new class or selecting from an existing implementation. like a dialog box. you need to create a class derived from the CPropertyPage base class to implement your application-specific functionality. The ID of the dialog box template resource is enumerated as the familiar IDD value in the class definition like this: enum { IDD = IDD_PROPPAGE_FIRST }. Creating a CpropertyPage-derived handler class for the property page. the property page has a DoDataExchange() func tion so that you can exchange data between the controls and mapped member variables with the usual DDX macro entries. which you easily can generate by using the ClassWizard Member Variables tab. Lecturer in Computer Science. The ID then is passed down into the CPropertyPage base class by the constructor function like this (excluding the ClassWizard lines): CFirstPropertyPage::CFirstPropertyPage() : CPropertyPage(CFirstPropertyPage::IDD) { } You'll also notice that. Thirupathi MCA. the New Class dialog box then lets you specify a specific name for your new class.

By overriding the default zero value in the iSelectPage parameter.WEB AND VISUAL PROGRAMMING (VC++ 6. KCCS Warangal .DoModal()==IDOK) { AfxMessageBox("Retrieve data from property sheet"). Creating a CPropertySheet-Derived Class After you create a CPropertyPage-derived class to handle each page in the property sheet. The two constructors are defined like this: CSampleSheet(UINT nIDCaption. void CPropSheetSampleDoc::OnPropertysheetDisplay() { CSampleSheet psSample("Sample Property Sheet"). The only difference between the two constructors is that the first needs a resource for a string table resource. Now that you have a CPropertySheet-derived class and some CPropertyPagederived classes. if (psSample. CWnd* pParentWnd = NULL.. UINT iSelectPage = 0)..64 - . CWnd* pParentWnd = NULL.0) have the usual ClassWizard comment placeholders to let you add handler functions from the Message Maps tab. you can create a new class to extend the CPropertySheet functionality to cope with your application-specific purpose and tie together the individual property pages. you have all the elements needed to construct and display a property page object.. By R.AddPage(new CSecondPropertyPage). as in this example: #include "FirstPropertyPage.h" // . Thirupathi MCA. the whole sheet can be displayed like a modal dialog box by calling the CPropertySheet's DoModal() function. Lecturer in Computer Science. you'll see that it includes a couple of very similar constructor functions and a message map. psSample. you can make a property page other than the first display initially. psSample. At this point. you can use its AddPage() function to add the CPropertyPage-derived objects. but the second takes a pointer to a string to specify the required caption. you can add mapping variables and event handlers for the various property page controls in the same way as you would for a dialog box.h" #include "SecondPropertyPage. After the pages are added. Adding the Property Pages After constructing a CPropertySheet-derived object. CSampleSheet(LPCTSTR pszCaption. You can repeat the same process of adding a property page handler class for each of the property pages in your property sheet as if they were individual dialog boxes.AddPage(new CFirstPropertyPage). If you take a look at the new class definition. UINT iSelectPage = 0).

GetPage(1). A modeless property sheet is created without the OK. } this: The greatly simplified code required to display the property sheet now is like CSampleSheet psSample("Sample Property Sheet").. you'll need to override the CPropertySheet's OnCreate() function and add the buttons manually. Lecturer in Computer Science. By R. However. you can embed the property sheet objects in your derived CPropertySheet class. two property page objects are instantiated and added. Your property sheet constructor would be modified to add the two member property pages: CSampleSheet::CSampleSheet(LPCTSTR pszCaption. After the sample property sheet is constructed. CWnd* pParentWnd. This solution may be more elegant for situations where the pages used in the property are always the same and the property sheet is instantiated in several places. like this class-definition fragment: protected: CFirstPropertyPage m_pageFirst. Adding the pages outside the property sheet gives you some flexibility as to which pages should be added. You'll also notice that the GetPage() function is used to return the pointer to the property page objects.65 - . and Apply buttons. If you need these buttons on a modeless dialog box. In this situation. KCCS Warangal . pParentWnd. AddPage(&m_pageSecond). Thirupathi MCA. Cancel. delete psSample. but it may be closed using the sheet's system menu or close button. CSecondPropertyPage m_pageSecond.WEB AND VISUAL PROGRAMMING (VC++ 6. if (psSample. you could call AddPage() to add the property pages inside the property sheet's constructor function (as embedded objects). The DoModal() call returns IDOK if the OK button was clicked just as it would for a dialog box. iSelectPage) { AddPage(&m_pageFirst). UINT iSelectPage) :CPropertySheet(pszCaption.GetPage(0).DoModal()==IDOK) AfxMessageBox("Ok"). Creating a Modeless Property Sheet You can create a modeless property sheet simply by calling the CPropertySheet's Create() function rather than its DoModal() function.0) } } delete psSample.

delete m_pPSSample. KCCS Warangal . Lecturer in Computer Science..66 - . The modeless property sheet is created as a child of the application's main window by the Create() call if the object doesn't already exist. Thirupathi MCA. } } void CPropSheetSampleDoc::OnPropertysheetClose() { if (m_pPSSample) { m_pPSSample->DestroyWindow(). m_pPSSample->Create(AfxGetMainWnd()). The following code fragment illustrates these concepts: CPropSheetSampleDoc::CPropSheetSampleDoc() : m_pPSSample(NULL) { } CPropSheetSampleDoc::~CPropSheetSampleDoc() { if (m_pPSSample) delete m_pPSSample. } void CPropSheetSampleDoc::OnPropertysheetDisplay() { if (m_pPSSample==NULL) { m_pPSSample = new CSampleSheet("Modeless Property Sheet"). you may want to make the property sheet responsible for its own tracking by overriding the PostNcDestroy() virtual function and delete the C++ this pointer to free the property sheet memory.WEB AND VISUAL PROGRAMMING (VC++ 6. } } This code assumes that the property pages are created inside the property sheet's constructor and that the m_pPSSample property sheet pointer is declared in the document class definition like this: CSampleSheet* m_pPSSample.0) A modeless property sheet object should be created with the C++ new operator and tracked by a pointer embedded in a holding class responsible for deleting the allocated property sheet object after its window is closed. By R. Alternatively. The OnPropertysheetDisplay() function is a menu handler function that allows the user to create the modeless property sheet. You can force a modeless property sheet window to close from within your code by calling its DestroyWindow() function. m_pPSSample = NULL.

Lecturer in Computer Science. The WM_INITDIALOG message is sent only once to a property page when it is first displayed. Responding to Property Sheet Messages A host of messages are transmitted around a property sheet during its lifetime. such as EnableWindow(). The base class implementation of OnKillActive() calls UpdateData(TRUE). These messages are essentially the glue that holds together the various pages.. Your property page window and controls are active after the call to the base class CPropertyPage:: OnInitDialog() handler function. or FALSE if the page was not initialized successfully. KCCS Warangal . The base class implementation of OnSetActive() calls UpdateData(FALSE) so that your overridden DoDataExchange() function is called to transfer data from your mapped member variables into the page's controls. By adding DDX_ and DDV_ macros to your derived class's DoDataExchange() function.67 - . but a set of activation messages also is sent from the header control to indicate when each page is becoming active or inactive. You can provide an override for OnSetActive() in your derived class to perform any initialization required when that page is about to be redisplayed. Your override function should return a TRUE value if the page was initialized successfully. At this point.0) The OnPropertysheetClose() function is another menu handler function that demonstrates how the property sheet can be closed from within the code with a call to DestroyWindow(). the first message that is sent to the initial property page is the WM_INITDIALOG message. and parent property sheet window. Initializing the Property Pages After the property sheet has been displayed. Property Page Activation and Deactivation Whenever a particular property page is activated. Thirupathi MCA. which then calls the OnSetActive() virtual function. header control. You can trap this message in your CPropertyPage-derived class in a normal OnInitDialog() handler function. The pages themselves act like a series of independent dialog boxes. you can call window-based functions on any of your subclassed control-mapping objects (such as those added by ClassWizard). This notification is handled in the CPropertyPage base class. This means that any pages in the property sheet that haven't yet been displayed will not perform OnInitDialog(). you can transfer any data from the controls to your mapped member variables and perform By R. This only-on-demand initialization of property pages makes for fast and efficient property sheets that need to initialize only the pages that actually are selected by the user. this calls through the DoDataExchange() function in save and validate mode.WEB AND VISUAL PROGRAMMING (VC++ 6. You also can subclass your own controls inside the OnInitDialog() handler. it is sent a PSN_SETACTIVE notification message from the header control.

If you override OnReset() and don't call the base class function. After all of the OnOK() functions have been called and returned in each of the property pages. When the property sheet is opened. OnCancel() isn't performed..WEB AND VISUAL PROGRAMMING (VC++ 6. you can stop the cancellation from proceeding. Handling Messages from OK. but a TRUE value lets the cancellation continue as normal. OnCancel(). the base class implementation calls the OnOK() virtual function and resets the modified flag in each of the property pages. You can return a FALSE value from your OnApply() override to stop the changes from proceeding (and inform the user). OnReset() is called in response to the PSN_RESET notification.68 - . the OnKillActive() function isn't called before OnCancel() so that the user can always close the property sheet (unless you explicitly disable the Cancel button). which can be passed in the two parameters of the QuerySiblings() function. If you don't add an override for OnApply() to your derived property page class. By returning FALSE from OnQueryCancel(). Thirupathi MCA. PSM_QUERYSIBLINGS lets you pass two values. You can pass FALSE to SetModified() to reset the page's modified flag. If you can't preserve the original settings. an OnOK() virtual function is called for each of those property pages that have been displayed during the lifetime of the property sheet. you should call that page's SetModified() function. This sends a PSM_QUERYSIBLINGS message to each of the other property pages in turn. After the Apply button is clicked. passing a TRUE value. Like other user-defined messages. You can add any additional validation not performed in the DoDataExchange() function to OnKillActive() itself. Whenever a setting in one of the property pages is changed. You also can close the property sheet by calling the CPropertySheet's EndDialog() function. Sending Messages Between Property Pages You can send user-defined messages between the active property pages of a property sheet by calling the pages'QuerySiblings() member function. However. Lecturer in Computer Science. If you want to conditionally stop the property sheet from closing after OK is clicked. Apply. A corresponding virtual function.0) validation specific to your property page. a PSN_APPLY notification is sent to the property pages. Apply means apply those changes without closing the property sheet. By R. until one of the pages returns a non-zero value. and Cancel Buttons After the property sheet's OK button is clicked. a WPARAM and a LPARAM. the Apply button is disabled. KCCS Warangal . you should return a FALSE value from your OnKillActive() overridden function. which actually posts a PSM_PRESSBUTTON message with a PSBTN_CANCEL value to the property sheet to close it. is called in the same way after the Cancel button is clicked. the property sheet will be closed. you can call the CancelToClose() member function of CPropertyPage after applying your changes.

. passing the two operands for the multiplication request.lRes). the default action is to stack them to produce rows of tabs. } Notice the message map entry for the PSM_QUERYSIBLINGS message. By R.LPARAM lParam) { AfxMessageBox("Got the message. b = 456. lRes. The following code implemented in the first property page shows the corresponding message map entry and handler function for the query: BEGIN_MESSAGE_MAP(CFirstPropertyPage. CString strAnswer.0) The following code implemented in a button message handler in the second property page initiates the interpage communication: void CSecondPropertyPage::OnMakeChange() { SetModified().b. Customizing the Standard Property Sheet A number of CPropertySheet member functions let you change the standard property sheet appearance. Lecturer in Computer Science. Thirupathi MCA. CPropertyPage) //{ { AFX_MSG_MAP(CFirstPropertyPage) // NOTE: the ClassWizard will add message map macros here //} } AFX_MSG_MAP ON_MESSAGE(PSM_QUERYSIBLINGS. and few functions can radically change the standard functionality. then is displayed in the message box in line 8. but you can use the SetTitle() member function to change this title. and the second lets you optionally pass a PSH_PROPTITLE flag to prefix your title with the text "Properties for". int a = 123.69 - . When the tabs of a property sheet can't all be displayed along one line. which is returned from the query to the second page.. KCCS Warangal . SetTitle() requires two parameters. Calculating!"). Its corresponding handler function merely displays a message box and returns the result of the multiplication.Format("Result of %d * %d = %d".OnQuerySiblings) END_MESSAGE_MAP() 8: LRESULT CFirstPropertyPage::OnQuerySiblings(WPARAM wParam.. The first is a pointer to the new caption. return wParam * lParam. The result. as . AfxMessageBox(strAnswer). strAnswer. You would normally set the property sheet title in the constructor. The call is made to QuerySiblings() on line 5. LRESULT lRes = QuerySiblings(a.WEB AND VISUAL PROGRAMMING (VC++ 6.a.b). } // Save Changes.

even after it has been displayed. Similarly.0) A property sheet with stacked tabs.70 - . You can change this behavior by calling the property sheet's EnableStackedTabs() function and passing a FALSE value. Property Page Management You can add a page at any time during the life of a property sheet. Thirupathi MCA. you can use RemovePage() and pass a zerobased page index number or a pointer to a specific page to remove that page.WEB AND VISUAL PROGRAMMING (VC++ 6. as A property sheet with scrollable tabs.. Lecturer in Computer Science. By R. This action displays all the tabs along the same line and adds two scroll arrows to let the user scroll through the tabs. The tab control is updated automatically after you call AddPage() so that the user can select it. KCCS Warangal .

By R. KCCS Warangal . For example. you can find this directly by calling GetActivePage(). the following property sheet OnInitDialog() override adds an image to each tab from an image list (of 8x8 pixel images) held as a bitmap in IDB_IMAGE_LIST: BOOL CImagePropertySheet::OnInitDialog() { BOOL bResult = CPropertySheet::OnInitDialog(). Creating a Wizard Mode Property Sheet Wizards are property sheets with Back and Next buttons instead of tabs to allow users to sequentially traverse the property pages. You can find the number of pages a property sheet holds. The corresponding GetPage() function returns a pointer to the CPropertyPage object specified by an index value. Lecturer in Computer Science.8.0) If you find the zero-based index for a specific page. The current active page number is returned from GetActiveIndex(). if (pTabCtrl) { pTabCtrl->SetImageList(&m_ImageList). The corresponding SetActivePage() lets you set a new active page specified by a zerobased index or a pointer to the desired page.iImage = i. and instantly the property sheet is transformed into a wizard. } } return bResult. Thirupathi MCA.255.mask = TCIF_IMAGE.8. Just one call to the property sheet's SetWizardMode() function is required before the sheet is displayed.255)). CTabCtrl* pTabCtrl = GetTabControl(). pTabCtrl->SetItem(i.RGB(255. tcItem. for(int i=0.WEB AND VISUAL PROGRAMMING (VC++ 6. which is returned from the sheet's GetPageCount() function.. tcItem.i<pTabCtrl->GetItemCount().Create(IDB_IMAGE_LIST. } The m_ImageList member in this listing is defined as a CImageList object in the CImagePropertySheet class definition. m_ImageList. If you'd prefer a pointer to the active page. you can use the GetPageIndex() function to return the index by passing the function a pointer to one of the sheet's CPropertyPage objects. Turning a normal property sheet into a wizard is simple.&tcItem). The example iterates through the tabs.71 - . setting one of the images against each tab. You'll usually see these buttons used in installation and configuration tasks where users can proceed to the next step only after they've successfully completed the current page.i++) { TCITEM tcItem.

You'll probably want to disable some of the buttons at various stages. You must call SetWizardButtons() only after the property sheet has been displayed. By R. PSWIZB_FINISH Show the Finish button instead of the Next> button. and display a Finish button on the last property page. the same function can test the current page to check whether it is at the start or the end of a wizard sequence. If this is true. The following code fragment demonstrates these principles by overriding OnSetActive() in a derived CPropertyPage class.WEB AND VISUAL PROGRAMMING (VC++ 6. The OnSetActive() virtual function in the property sheet is a good candidate for calling SetWizardButtons(). KCCS Warangal . Thirupathi MCA. it disables the <Back button. You can use the window's GetParent() function to get to the property sheet object from a property page and access SetWizardButtons() through the pointer (after casting it) returned from GetParent(). at the end.. You can pass and combine a set of flag values to specify the required customization. The example assumes that the same class (or base class) will be used to implement all the property pages in a property sheet. PSWIZB_DISABLEDFINISH Show a disabled Finish button instead of the Next> button. The property sheet's SetWizardButtons() function lets you do just that. const int nPageNo = pParentSheet->GetActiveIndex().0) A Wizard mode property sheet.72 - . At the start.GetParent()). Flag Values for Customizing the Wizard Buttons Description Flag Value PSWIZB_NEXT Enable the Next> button. it displays the Finish button: BOOL CWizProppage::OnSetActive() { CPropertySheet* pParentSheet = STATIC_DOWNCAST(CPropertySheet. PSWIZB_BACK Enable the <Back button. because it manipulates the property sheet buttons directly. Lecturer in Computer Science.

if so just enable back and show finish if (nPageNo == pParentSheet->GetPageCount()-1) pParentSheet->SetWizardButtons(PSWIZB_BACK|PSWIZB_FINISH). The next three (optional) parameters let you specify an HBITMAP handle for the background bitmap. The new features let you set a background bitmap in a property sheet and let property pages display both titles and subtitles. and an AddPage() function that takes a pointer to the new CPropertyPageEx pages. These are introduced to support the new features included with Windows NT 5 and Windows 98 (and will only work properly on these platforms). these features are available only for wizard-style property sheets. A set of associated flag values lets you tailor the specific details of the new wizard look. There is a corresponding Construct() function with parameters identical to the constructors for vectoring property sheets. if so just enable next if (nPageNo == 0) pParentSheet->SetWizardButtons(PSWIZB_NEXT). parent window.73 - . so that only the button with your text and the Cancel button are displayed. an HPALETTE handle for the bitmap's palette. however. and an HBITMAP handle for the property sheet's header section. These flags can be combined with a logical OR to add or remove certain presentational aspects of the Wizard97 property sheet style. } You can further customize the Finish button by changing its caption with a call to SetFinishText() and passing it a pointer to the required caption text. return CPropertyPage::OnSetActive(). KCCS Warangal . SetFinishText() also has the effect of removing the <Back button. You must add the PSH_WIZARD97 flag value to the dwFlags member of this structure before displaying the property sheet to use any of the new features. At the time of writing. You can access the CPropertySheetEx class's m_psh member to change the Win32 PROPSHEETHEADER structure directly. and initial page—are identical. The first three parameters—the caption.WEB AND VISUAL PROGRAMMING (VC++ 6. Lecturer in Computer Science. // Is this the last page. Flag Values for Customizing the Wizard97 Property Sheet Flag Value PSH_WIZARD97 Description Sets the Wizard97 mode. You must always set this flag if you want to use the new wizard features. You can pass a NULL value to any of these parameters if the parameter isn't required.0) // Is this the first page.. CPropertySheetEx extends CPropertySheet. and the only real difference is the additional constructor parameters. Using the New CPropertySheetEx and CPropertyPageEx Classes The Visual C++ 6 MFC provides two new property sheet and page classes: CPropertySheetEx and CPropertyPageEx. By R. Thirupathi MCA.

and an ID for a subtitle. KCCS Warangal .0) Description The watermark (background) bitmap style should be used. You can set this flag to stretch the bitmap to cover the property sheet. a string resource ID for a caption. The property sheet background bitmap then is used to fill the entire property sheet. PSP_USEHEADERSUBTITLE Displays the subtitle line. PSH_USEPAGELANG You should set this flag if you want the property sheet language settings to inherit from the first property page's resource template. PSH_USEPLWATERMARK Uses the supplied hplWatermark palette handle rather than the default palette. The new CPropertyPageEx lets you specify both a title and subtitle for each property page. PSH_USEHBMHEADER Used with PSH_HEADER to specify that the hbmHeader bitmap handle is used instead of using the pszbmHeader string pointer to specify the header bitmap. as well as the normal caption. which can be combined with a logical OR. PSP_USEHEADERTITLE Displays the header text line. there is a corresponding Construct() function with identical parameters to allow for arrays of property pages. You can let all but the first parameter (the dialog box template) default to zero if you don't need specific features. PSH_USEHBMWATERMARK Used with PSH_WATERMARK to specify that the hbmWatermark bitmap handle is used instead of using the pszbmWatermark string pointer to specify the watermark bitmap. lists the new flag values. another ID for the header title. Thirupathi MCA. Lecturer in Computer Science.74 - . As you'd expect by now. Flag Values for Customizing the Wizard97 Property Page Flag Value PSP_HIDEHEADER Description Hides the header section of the property page (when in Wizard97 mode). You can access the m_psp PROPSHEETPAGE structure member to add some new flag values to the property page structure's dwFlags member. These flags are used with the Wizard97 property page style to customize the appearance of each property page. PSH_STRETCHWATERMARK By default. Flag Value PSH_WATERMARK By R.. the background image is tiled over the property sheet area.WEB AND VISUAL PROGRAMMING (VC++ 6. The CPropertyPageEx class extends CPropertyPage and just supplies constructor functions to support the new features. PSH_HEADER You should set this flag to use a bitmap in the property sheet header section. The CPropertyPageEx constructor lets you specify a resource dialog box template ID.

Thirupathi MCA.bmBackground.AddPage(pNewPage1). When run.0) The last two flags. with the property sheet background bitmap (IDB_BACKGROUND) filling the wizard dialog box. bmBackground. NULL. CBitmap bmBackground. CPropertySheetEx pex("New Property Sheet". IDS_PAGE_CAPTION1. IDS_SUBTITLE1). only the base classes are used.AddPage(pNewPage).m_psh. IDS_PAGE_CAPTION1.dwFlags |= PSP_HIDEHEADER.dwFlags |= PSH_WIZARD97.75 - .bmHeader). however.. pex. you probably would want to derive your own classes from the CPropertySheetEx and CPropertyPageEx classes. Lecturer in Computer Science. PSP_USEHEADERTITLE and PSP_USEHEADERSUBTITLE. IDS_SUBTITLE1).NULL. bmHeader. By R. pex. The following code lines show how two bitmap resources can be loaded and then displayed in the body and header sections of the property sheet.WEB AND VISUAL PROGRAMMING (VC++ 6.LoadBitmap(IDB_BACKGROUND). pex. pex.0.LoadBitmap(IDB_HEADER). CPropertyPageEx* pNewPage1 = new CPropertyPageEx(IDD_PROPPAGE_FIRST. In a real piece of code.IDS_HEADER_TITLE1. this code displays the first property page without the header. pNewPage->m_psp. CPropertyPageEx* pNewPage = new CPropertyPageEx(IDD_PROPPAGE_FIRST. are set when you pass the title and subtitle resource IDs to the property sheet constructor function. KCCS Warangal .DoModal(). A Wizard97 property page with the header hidden.IDS_HEADER_TITLE1. Two property pages are constructed and added to the property sheet. To simplify the code. CBitmap bmHeader.

dwFlags member. even though no current property pages implement help support.76 - . otherwise. The Help button then will be displayed when the property sheet window is created.WEB AND VISUAL PROGRAMMING (VC++ 6. Thirupathi MCA. You should combine the PSP_HASHELP flag with the current dwFlags set in the page's m_psp PROPSHEETPAGE structure before displaying the property sheet. if you are dynamically adding pages after the property sheet has been dis played. so you must add the message map and handler function manually: BEGIN_MESSAGE_MAP(CMyPropertyPage.dwFlags |= PSP_HASHELP. Lecturer in Computer Science. showing the caption.OnHelp) END_MESSAGE_MAP void CMyPropertyPage::OnHelp() { AfxMessageBox(IDS_HELP_RESPONSE). The Help button then is added to the property sheet and is enabled for each page that sets the PSP_HASHELP flag.. After you add the Help button. you can add a handler for the ID_HELP command message notification sent whenever the user clicks the Help button. Alternatively. you can ensure that the Help button is added by setting the PSH_HASHELP flag in the property sheet's m_psh. header line. Adding Help Buttons and Help Support You can add a Help button to a property sheet by adding the PSP_HASHELP flag value to each property page that will support help. you could add a line like this to the property page constructor: m_psp. A Wizard97 property page showing the header and subtitle lines.0) The second page is displayed with the new header style. and subtitle line. KCCS Warangal . ClassWizard doesn't automate this command message handler.CPropertyPage) ON_COMMAND(ID_HELP. } By R. the button is disabled. For example.

like this: #include "afxpriv.. By R. This generates a WM_HELPINFO message that can be handled by an OnHelpInfo() handler added to the property sheet or one of the property pages.h" void CSampleSheet::OnHelp() { SendMessage(WM_COMMANDHELP). KCCS Warangal .0) Instead of displaying the message box as shown here. you normally would invoke your application's helper application. you can add an OnHelp() handler function to the property sheet class and add code to send a WM_COMMANDHELP message to the active property page using SendMessage(). } Note The afxpriv.h header file must be included to provide the definition of the WM_COMMANDHELP message.WEB AND VISUAL PROGRAMMING (VC++ 6. Thirupathi MCA.77 - . If you want to make the Help button use the same handler function as the context-sensitive F1 help. Lecturer in Computer Science. Users can access context-sensitive help from the property sheet by pressing the F1 key.


you can create a device context for the screen like this: CDC dc. You can retrieve this handle with the device context's GetSafeHdc() function. coordinate mapping functions.79 - .NULL). you can perform a number of drawing operations or other device context–specific functions. font-manipulation and rendering functions. such as CView::OnDraw() and CView::OnBeginPrinting(). you can use the CWnd::GetWindowDC() function instead. You often will be handed a pointer to an initialized CDC object from MFC framework functions. printer-specific functions. The CreateDC() function lets you initialize the device context for a specific device with a driver and device name. Otherwise. You can even get a pointer to the entire Windows desktop by calling GetDesktopWindow()->GetWindowDC(). KCCS Warangal . You then can initialize it in a number of ways.NULL. however. path-tracking functions.CreateDC(NULL. NULL). clipping functions. For example. The basic CDC class is huge and supports all the GDI drawing functions. The MFC provides wrapper classes for the device-context object as the CDC base class. the driver's own defaults are used. NULL. Thirupathi MCA. By R. NULL. After you obtain a pointer to the device context. dc. which retrieves the device context and lets you pass a flag value to control the clipping of the returned device context. The actual Win32 device-context handle is accessible via the public m_hDC member. The last parameter lets you pass a DEVMODE structure that can be used to set specific initialization defaults.. where the m_hDC member is invalid.CreateDC("Display". they are represented by HDC device-context handles.0) Device Contexts in MFC Device contexts are Win32 objects. as well as a number of more specialized derived classes. dc. Or you could create a device context for a printer like this: CDC dc. You also can use the GetDCEx() function. If you want a CDC pointer for the entire window area (including the title bar and borders). If you have obtained the pointer to a window's device context via GetDC(). and metafile-playing functions. The CDC constructor function constructs an uninitialized device context. The CDC Class The CDC base class encapsulates all the device-context functionality and drawing functions that use a Win32 HDC object. you must call CWnd::ReleaseDC() on the same CWnd object to release that window's device context for other applications to use."Cannon Bubble-Jet BJ330".WEB AND VISUAL PROGRAMMING (VC++ 6. Lecturer in Computer Science. You also can obtain a pointer to a CDC object for the client area of a window using the CWnd::GetDC() function.


If you just want to retrieve information regarding the capabilities of a device, you can use the CreateIC() function and then use the GetDeviceCaps() function to retrieve the cap abilities of the specified device. The GetDeviceCaps() function can be used with any device context, but a device context created with CreateIC() is a special cut-down device context that only supplies information about a device and cannot be used for drawing operations. You can use the CreateCompatibleDC() function to create a memory context compatible with a reference device context supplied as a pointer to CDC object. The memory device context is a memory-based representation actual device. If you pass NULL as the reference device context, a memory context is created that is compatible with the screen. Note device a real of the device

Memory device contexts created with CreateCompatibleDC() are created with a minimum monochrome bitmap. If you want to copy color images between a memory device context and the screen, you must create a compatible memory bitmap. If you have created a device context (instead of obtaining one via GetDC() or using a pointer to a framework device context), you should delete the Win32 devicecontext object after use by calling the DeleteDC() member function. If you just want to quickly create and attach a temporary CDC object to an HDC handle, the FromHandle() function allocates and attaches a CDC object for you, returning the pointer. You can find the window associated with a device context by calling the device context's GetWindow() function, which returns a CWnd pointer to the associated window.

When you call SaveDC(), an integer is returned identifying the saved instance (or

You can save and restore all these settings by using SaveDC() and RestoreDC().

zero, if it fails). You later can pass this integer to RestoreDC() to restore those saved defaults. The CClientDC Class You can use the CClientDC class to quickly connect a CDC object to a window by passing a pointer to the desired window. This is equivalent to constructing a CDC object and attaching an HDC handle obtained from a window with the Win32 ::GetDC() function. If the constructor succeeds, the m_hWnd member variable is initialized with the handle of the window donating the HDC handle; otherwise, a CResourceException is raised. When the CClientDC() object falls out of scope or is deleted, the Win32 device context object (HDC) is released automatically. For example, you might want to access the client device context of a view window from a view-based menu handler to draw a circle, like this: void CCDCBaseView::OnDrawEllipse() {

By R. Thirupathi MCA., Lecturer in Computer Science, KCCS Warangal
- 80 -


CClientDC dcClient(this); dcClient.Ellipse(0,0,100,100); } You will notice that the C++ this pointer simply is passed to the CClientDC constructor to initialize the device context with the view's client device context. After initialization, the circle can be drawn in the view using the CDC::Ellipse() function. Finally, the destructor of the CClientDC object ensures that the view's HDC is released. The CPaintDC Class A CPaintDC object is constructed in response to a WM_PAINT message. If you add a handler for this message, you will see that ClassWizard automatically generates an OnPaint() handler starting with the following line: CPaintDC dc(this); // device context for painting The CPaintDC constructor automatically calls the BeginPaint() function for you. The BeginPaint() function is responsible for initializing a PAINTSTRUCT structure. PAINTSTRUCT holds information about the smallest rectangle that needs to be redrawn in response to an invalid portion of a window. The PAINTSTRUCT information is available through the m_ps member, and the attached window handle can be found from the m_hWnd member. When the object falls out of scope and its destructor is invoked, the EndPaint() function is called to complete the usual WM_PAINT procedure and mark the invalid region as valid. The CMetaFileDC Class A Windows metafile is a file that contains a list of GDI drawing instructions required to render an image in a device context. The metafile can be stored on disk, reloaded on another computer with different display capabilities, and redrawn by repeating the drawing instructions to produce a similar image. You can always play a metafile using the CDC base class's PlayMetaFile() and passing a handle to a metafile object. The CMetaFileDC class lets you also create and record metafiles, however. To record a metafile, you should construct a CMetaFileDC object. Then call Create() or CreateEnhanced() to create a simple or enhanced metafile on disk passing a filename and a reference device context for the enhanced metafile. The details of these drawing operations are stored in sequence in the metafile as you call each drawing function. Finally, you should call CMetaFileDC::Close() or CMetaFileDC::CloseEnhanced() to close the metafile. The close functions return an HMETAFILE or HENHMETAFILE handle, which can be used by the Win32 metafile manipulation functions, such as CopyMetaFile() or DeleteMetaFile().

By R. Thirupathi MCA., Lecturer in Computer Science, KCCS Warangal
- 81 -


Brushes and Pens The main purpose of a device context, however, is to provide a uniform drawing surface for the GDI rendering func tions. These rendering functions use two main GDI objects to draw lines and filled areas. Lines are drawn with objects called pens, and filled areas are drawn with objects called brushes. These two objects are represented at the Win32 level by the HPEN and HBRUSH handles. All of the GDI objects, including pens and brushes, are wrapped by the CGdiObject MFC base class. Although the CGdiObject is not strictly an abstract base class, you normally would construct one of its derived classes, such as CPen or CBrush.
CGdiObject is responsible for manipulating these handles and provides member functions such as Attach() and Detach() to attach the object to a GDI handle and detach it after use.

The handle itself is stored in the m_hObject member, which you can retrieve by calling the CGdiObject::GetSafeHandle() function. A static function called FromHandle() lets you dynamically create a CGdiObject for the duration of a Windows message. This object then is deleted by DeleteTempMap() when the thread returns to the Windows message loop. The DeleteObject() function deletes the underlying GDI object from memory, so you are free to reuse the same CGdiObject by calling one of the derived classes'Create() functions to create another GDI object. The CGdiObject class is extended by the MFC CPen and CBrush classes, which greatly simplify creating and manipulating these two drawing objects. This section shows you how these classes are constructed and used. Pens and the CPen Class Pens are used to draw lines, curves, and the boundaries of filled shapes, such as ellipses, polygons, and chords. You can create pens of various sizes, styles, and colors (even invisible pens for drawing shapes without outlines), and then select a pen into the device context and draw with it. You can select only one pen into a device context at any time. The old pen is swapped out automatically when you select a new pen. There are two main pen types: cosmetic and geometric. The cosmetic pens are simple to create and quick to draw with. The geometric pens support more precise world units and let you use complex patterns and hatching effects in ways similar to brushes. You can create a variety of pens using the CPen constructor. There are two versions of the constructor. You can pass one version of the constructor a set of style flags, the pen width, and a COLORREF to indicate the color of the new pen. Simple Pen Styles Style PS_SOLID Pen Description Draws in a solid color.

By R. Thirupathi MCA., Lecturer in Computer Science, KCCS Warangal
- 82 -

The other constructor form lets you supply a pointer to a LOGBRUSH structure to initialize the attributes of a geometric pen. the current object is deselected automatically. You can use some additional flags to change the mitering (how lines are joined) and end-cap styles (how lines end). PS_ENDCAP_SQUARE You also can construct an uninitialized pen by using the default constructor. Makes the ends of lines square. PS_ENDCAP_FLAT Makes the ends of lines flat. PS_GEOMETRIC Specifies a geometric pen.. You also can use the device context's SaveDC() and RestoreDC() functions to reselect the original pens and release your created pen. PS_DASHDOT. Draws in a dotted style. Advanced Pen Styles Style Pen Description PS_COSMETIC Specifies a cosmetic pen. PS_JOIN_BEVEL Draws beveled.WEB AND VISUAL PROGRAMMING (VC++ 6. and PS_DOT styles only work with pens that have a width of 1 pixel. PS_ALTERNATE Sets every other pixel (only cosmetic pens). Draws in a dashed style. joined lines. PS_JOIN_ROUND Draws round. Selecting Pens into the Device Context You can select all of the GDI objects by using the device context's overloaded SelectObject() function. Table 6. joined lines.83 - . KCCS Warangal . PS_JOIN_MITER Draws mitered. By R. You then initialize it by using CreatePen() and passing the same parameters as the two constructors for the CPen class. When you select your new object. otherwise. The PS_DASH. PS_USERSTYLE Uses the user-style DWORD array to create the dash-dot pattern. PS_ENDCAP_ROUND Makes the ends of lines round. Draws alternating dashes and dots. You should save the pointer to this deselected object to reselect it when you finish drawing with your pen. You also can pass an array of DWORD values to specify complex dot and dash patterns. or by using CreatePenIndirect() and passing a pointer to a LOGPEN structure that holds the pen-initialization details.2.0) Style PS_NULL PS_DASH PS_DASHDOT PS_DOT PS_INSIDEFRAME Note Pen Description Uses an invisible pen. Draws lines inside filled areas. Lecturer in Computer Science. The SelectObject() function that accepts a CPen object returns a pointer to the currently selected CPen object. Thirupathi MCA. joined lines. they are drawn as solid lines.

The PolyDraw() function lets you draw a number of con nected lines and B[as]ezier splines. the currently selected pen is returned from SelectStockObject(). passing the same index values to create a stock CPen object. The sample OnDraw() function using different drawing functions in a variety of pens to produce the output shown By R. ArcTo(). You also can use the area-filling functions to draw only the outline of a shape by selecting a NULL brush. You can find the current graphics position from GetCurrentPosition(). You can change this position without drawing a line by using the device context's MoveTo() function. and AngleArc(). a black pen.84 - . These include a white pen. Other functions use brushes to fill an area and pens to draw the outline of that area. these objects are called stock objects. As usual. and a null pen. The LineTo() function draws a line from the current position to the specified position and updates the graphics cursor to the specified endpoint. BLACK_PEN.. You can select these straight into a device context by calling the CDC::SelectStockObject() function and passing the WHITE_PEN. The device context stores a current graphics cursor position. You can set the device context's default direction for these arcs to clockwise or counterclockwise by passing AD_CLOCKWISE or AD_COUNTERCLOCKWISE to the device context's SetArcDirection() function. You also can use the pen's base class CGdiObject::CreateStockObject() function. and many of the line-drawing functions use their starting point as the current graphics cursor position. You can plot a number of B[as]ezier splines (special type of curves) by using the PolyBezier() and PolyBezierTo() functions. Drawing with Pens A number of rendering functions use just pens. The PolylineTo() function performs a task similar to Polyline() but also updates the current graphics cursor. You can find the current direction by the flag returned from GetArcDirection(). or NULL_PEN index values.0) Using Stock Pens The operating system can lend out a number of common GDI objects to applications. and you can use PolyPolyLine() to draw a number of independent line sections. KCCS Warangal . Thirupathi MCA.WEB AND VISUAL PROGRAMMING (VC++ 6. Lecturer in Computer Science. You can draw elliptical arcs by using Arc(). as discussed in the following sections about brushes. You can use the Polyline() function to draw a number of lines from coordinates stored in an array of POINT structures. You can call the area-filling functions to outline the areas with the current pen. This value also affects the rendering of chords drawn with the Chord() function.

RGB(255.right.BottomRight()).RGB(255.Width()/3.rcDrw.y=((i%6)/3).WEB AND VISUAL PROGRAMMING (VC++ 6.0) Drawing with various pen styles.RGB(0.10.0)). h=rcClient. int w=rcClient.RGB(0. break.255)).5.i<rcClient.x*w+w.128.Height()/2.bottom). rcDrw.y*h+h). pDC->MoveTo(rcDrw.1. CPen penDash(PS_DASH.85 - . GetClientRect(&rcClient). CPen penDot(PS_DOT.0)). CPen penThick(PS_SOLID.1. Lecturer in Computer Science. An OnDraw() Function Using Different Pens to Create Graphics void CPensDemoView::OnDraw(CDC* pDC) { CPen penRed(PS_SOLID.0)). Thirupathi MCA.255)). // No Area Filling for(int i=0. CRect rcClient.DeflateRect(CSize(i. CRect rcDrw(x*w.0.left. CPen penDashDot(PS_DASHDOT. pDC->LineTo(rcDrw. switch(i%6) { case 0: pDC->SelectObject(&penThick).i)).i++) { int x=i%3.0. pDC->MoveTo(rcDrw.0. pDC->SelectStockObject(NULL_BRUSH).1.y*h.rcDrw..RGB(0.TopLeft()). KCCS Warangal .top). By R. int nSaved = pDC->SaveDC(). pDC->LineTo(rcDrw.Height()/6.0.

is derived from the CGdiObject base class. pDC->Pie(rcDrw. break. Another lets you pass a pointer to a CBitmap object to create a filling pattern.left+rcDrw. {(short)rcDrw. Whereas pens are used to draw lines.top).sizeof(pts)/sizeof(POINT)).top}. like other MFC GDI wrapper classes. The CBrush class wraps the GDI brush object and. Lecturer in Computer Science. case 4: pDC->SelectObject(&penDashDot). brushes are used to fill areas and shapes. One form lets you pass a COLORREF value for a solid-color brush.left. a pattern from a bitmap. pDC->Chord(rcDrw. } Brushes and the CBrush Class case 1: pDC->SelectObject(&penRed). break. break. KCCS Warangal . } case 3: pDC->SelectObject(&penDot).(short)rcDrw. rcDrw.right.BottomRight()).(short)rcDrw.bottom}}. Thirupathi MCA. pDC->Rectangle(rcDrw).rcDrw. pDC->Ellipse(rcDrw).rcDrw. rcDrw.86 - .WEB AND VISUAL PROGRAMMING (VC++ 6. pDC->SelectObject(&penDash). break. case 5: pDC->SelectStockObject(BLACK_PEN). The third form lets you pass an index describing a hatching technique and a COLORREF value to specify the hatchingpattern color. You can create brushes that fill an area with a solid color.CPoint(rcDrw.TopLeft().right. pDC->Polyline(pts. By R.0) } } pDC->RestoreDC(nSaved). You can use one of three constructor functions to construct brushes initialized with one of these filling techniques.. {(short)rcDrw.Width()/2. {(short)rcDrw.(short)rcDrw.bottom}. break.left. case 2: { POINT pts[] = { {(short)rcDrw. (short)rcDrw.BottomRight()). or a hatching scheme.bottom}.

or CreatePatternBrush()—to create the GDI brush object. The device context's SelectObject() function has an overload that accepts a pointer to a CBrush object and returns the previously selected CBrush object. KCCS Warangal . as Stock Brush Objects Stock Object Flag WHITE_BRUSH LT_GRAY_BRUSH GRAY_BRUSH DKGRAY_BRUSH BLACK_BRUSH HOLLOW_BRUSH. You can use a CreateSysColorbrush() function to create a brush initialized with one of the current system colors specified by an index value. NULL_BRUSH Brush Description White Light gray Gray Dark gray Black Transparent.WEB AND VISUAL PROGRAMMING (VC++ 6. The CreateBrushIndirect() function lets you initialize and pass a pointer to a LOGBRUSH structure to create the brush. it can use any of the drawing functions that draw filled shapes. Using Stock Brushes You can select a number of stock brushes into a device context with the SelectStockObject() function. You can use the CreateDIBPatternBrush() creation function to create a patterned brush from a device-independent bitmap (DIB). As with the pen. After you select your new brush. CreateHatchBrush(). You can set the style from a number of flag values to indicate what sort of brush you want with the lbStyle member of LOGBRUSH. By R. Selecting Brushes into the Device Context You can select a brush into a device context in the same way you would a pen. you must ensure that the brush is selected out of the device context before it falls out of scope or is deleted. like the NULL pen You also can use the CGdiObject base class's CreateStockObject() function to create a CBrush object initialized from a stock object flag.. Thirupathi MCA.0) Brush Hatching-Pattern Flags Style Brush Hatching HS_DIAGCROSS Diagonal crisscross HS_CROSS Horizontal crisscross HS_HORIZONTAL Horizontal lines HS_VERTICAL Vertical lines HS_FDIAGONAL Bottom-left to top-right lines HS_BDIAGONAL Top-left to bottom-right lines You can use the default constructor and then one of the creation functions—such as CreateSolidBrush().87 - . Lecturer in Computer Science.

however. SIZE. use the currently selected brush. The FloodFill() function lets you fill an area bounded by a specified color with the current brush. The CPoint. The RoundRect() function lets you draw rectangles with rounded corners.WEB AND VISUAL PROGRAMMING (VC++ 6. another CPoint object. and FillSolidRect() all render a filled rectangle from a set of rectangle coordinates. By R.88 - . pie segments using Pie(). respectively. CSize. FillRect(). These shapes are outlined with the currently selected pen. These two functions are similar to the Polyline() functions. They wrap POINT. or a DWORD value. let you pass a CBrush object by pointer to draw with that brush. because they take an array of POINT variables to define the polygon's vertices. You can call the OffSet() function to add an offset value to move the specified coordinates passing x and y coordinates. Many of the drawing functions can use CPoint objects as parameters. or a SIZE structure. These classes also let you manipulate and perform arithmetic operations on sets of coordinates. and CRect classes can hold point coordinates. so arithmetic between the various classes can be performed interchangeably. Rectangle(). Other functions draw a rectangle from a COLORREF value. You can use ExtFloodFill() to fill an area bounded by a specific color or fill an area of a specific color with the current brush. Some functions. You can draw filled polygons by using the Polygon() or PolyPolygon() function. or rectangles. and RECT structures and can be cast into each of these structures. which draws a single polygon or number of filled polygons. You can construct a CPoint object from two integers specifying the x and y coordinates. Lecturer in Computer Science. Overloaded operator functions accept these structures as parameters. MFC Classes for GDI Operations Many of the GDI functions use sophisticated MFC helper classes that let you specify coordinates in a two-dimensional coordinate system. such as FillRect(). another CPoint object. a SIZE structure. Thirupathi MCA. KCCS Warangal . This section examines these MFC coordinate-manipulation and storage classes in more detail. such as the Rectangle() function. When drawing polygons. respectively. you can specify one of two filling techniques: winding or alternate. and chord sections with the Chord() function. You can draw circles and ellipses using the Ellipse() function. The CPoint Class The CPoint class wraps a POINT structure to hold a single two-dimensional coordinate specified by its x and y member variables. size coordinates. such as FillSolidRect()..0) Drawing with Brushes You can use a number of device-context member functions with a brush to draw filled shapes. You can set these modes by using the SetPolyFillMode() function and passing the WINDING or ALTERNATE flag value. Most functions.

Some of the GDI and Windows functions require SIZE structures—usually to specify the size of an object (such as a window). subtract. Subtracts POINT.and right member integers. SIZE. The CSize Class The CSize class wraps a SIZE structure.WEB AND VISUAL PROGRAMMING (VC++ 6. a POINT structure. CSize Operator Overload Functions Description Operator = Copies the SIZE. You can construct a CSize object from two integers. bottom. or RECT values. or RECT values. or RECT values.. The CenterPoint() function is quite useful. CPoint Operator Overload Functions Description Operator = Copies the POINT. By R. SIZE. + Adds POINT. == Compares for equality with another SIZE or CSize object. != Compares for inequality with another POINT or CPoint. a SIZE structure. -= Subtracts a POINT or SIZE value from the CPoint object. += Adds a POINT or SIZE value to the CPoint object. != Compares for inequality with another SIZE or CSize object. you probably would use the CPoint's operator overloads to add. Many of these operators let you specify POINT.0) Mostly. or RECT values. which are declared as public accessible members. + Adds POINT. You will find that many of the CPoint and CRect functions and operators can take SIZE structure objects as parameters for arithmetic manipulation. SIZE.89 - . Thirupathi MCA. or BOOL values as appropriate. POINT. The CRect Class CRect is probably the most sophisticated of the coordinate storing classes. or compare two CPoint objects. however. or RECT structures as parameters and return SIZE. CRect wraps a RECT structure that exposes its coordinates as two coordinate pairs. You also can obtain these coordinates as CPoint objects returned by the TopLeft() and BottomRight() functions. -= Subtracts a SIZE value. SIZE. SIZE. This structure stores a two-dimensional size as cx and cy integer members. KCCS Warangal . Subtracts POINT. left. == Compares for equality with another POINT or CPoint. += Adds a SIZE value. Lecturer in Computer Science. or a DWORD value. These pairs correspond to the top-left and bottom-right points in a rectangle and are accessible from the RECT structure as the top.

the resulting CRect object is shaded. Lecturer in Computer Science. Subtracting one rectangle from another. also are provided by IntersectRect() makes the current CRect object the intersection rectangle of two source rectangles (where they overlap). += Offsets the rectangle by a POINT or SIZE value. it sets them to be so. you can call NormalizeRect() to fix them. you will find the PtInRect() member function useful. and subtraction functions IntersectRect(). or inflates each side by the coordinates of a RECT.0) because it returns a CPoint object representing the center of the rectangle. POINT. CRect Operator Overload Functions Description Operator = Copies the RECT.90 - . the resulting CRect object is shaded. and you can find the size represented as the CSize object returned from the Size() function.. if they are not. NormalizeRect() ensures that the top-left point coordinates are lower than the bottom-right coordinates. Thirupathi MCA. the resulting CRect object is shaded. UnionRect(). UnionRect() makes the CRect object the union of two source rectangles (the smallest rectangle that encloses both).WEB AND VISUAL PROGRAMMING (VC++ 6. If you are implementing drag and drop or want to perform bounds checking. If this is the case. You can find the width and height of the rectangle by using the Width() and Height() functions. union. which are overloaded to take a variety of parameter types. This returns TRUE if the specified point lies within the rectangle. Intersection. or pair of integers. KCCS Warangal . SubtractRect() sets its first RECT parameter's coordinates to the smallest rectangle that is not intersected by two overlapping rectangles (where the second rectangle encloses the first). The OffsetRect() function lets you move the position of the rectangle by an amount specified by a SIZE. You can increase and decrease the size of the rectangle by using the InflateRect() and DeflateRect() functions. You may find that some operations leave the coordinates in a condition where the width or height calculations may give negative results. Determining the union of two rectangles. and SubtractRect(). By R. Determining the intersection of two rectangles. Each of these functions requires that you previously called NormalizeRect().

Offsets or deflates the rectangle. CreateEllipticRgn() for ellipses. CreatePolygonRgn() for polygons. returning a RECT result. Thirupathi MCA. Returns the intersection. You can retrieve the HRGN handle by casting a CRgn object. and another RECT or CRect. you must construct it by using the default CRgn constructor and then use one of the creation functions. RGN_XOR. all GDI-rendering functions performed in the device context are clipped to the specified region. Offsets or inflates the rectangle. Compares for equality with another RECT or CRect. and NULLREGION flag values. If an error occurs when combining or selecting regions. You can specify complex regions that have overlapped borders. simple regions that do not have overlapping borders. Many of the functions use and return the type of region specified by the COMPLEXREGION. By R. By using the PtInRegion() or RectInRegion() function. you can perform complex bound checking. Sets the rectangle to the intersection of the rectangle's current value. RGN_OR. Lecturer in Computer Science. You can use the OffsetRgn() function to move a region and CopyRgn() to copy one region from another. you can select a region into a device context by using the device context's SelectObject() or SelectClipRegion() function. RGN_COPY. such as CreateRectRgn() for rect angles. Regions are used primarily for clipping. SIMPLEREGION. Thereafter.0) Operator -= + &= |= & | == != Description Offsets or deflates the rectangle. and another RECT or CRect. You can combine two regions by using the CombineRgn() function. This flag value can be any one of the following: RGN_AND. or RGN_DIFF (the nonoverlapping areas). returning a RECT result. You can test for equivalence between two regions with the EqualRegion() function. or CreateRoundRgn() for rounded rectangles. Sets the rectangle to the union of the rectangle's current value. or null regions where there is no specified region data. The CRgn Class and Clipping The CRgn class is another CgdiObject-derived GDI object wrapper class that wraps the HRGN GDI handle. KCCS Warangal . To create an initialized CRgn object. Returns the union.WEB AND VISUAL PROGRAMMING (VC++ 6. The two source regions specified by pointers to CRgn objects are combined using a logic operation specified by a flag as the last parameter.91 - .. Compares for inequality with another RECT or CRect. the ERROR flag is returned. Other functions are available that initialize from structures or create multiple polygons.

it is used whenever any of the text-output functions are called. and optionally a reference device context pointer to create the font. To create a font using CFont. It then constructs a font that is as close as possible to the one you have requested.WEB AND VISUAL PROGRAMMING (VC++ 6. You can pass a desired point size (in tenths of a point). you first must construct a CFont object with the default constructor and then call one of the font-creation routines. and typeface with its 14 parameters. After a LOGFONT structure is initialized. Whenever a new font object is created. Lecturer in Computer Science. You also can use CreatePointFontIndirect() to create a font from the lfHeight member set in a LOGFONT structure. a font must be selected into the device context before you can use it. The CFont class also has an HFONT operator to retrieve the underlying GDI handle when cast as an HFONT. effects. and the previously selected font is restored after use. height. Thirupathi MCA. and regions. clipping.92 - . Like pens. character set. font family. you can fill it with the details of a font by using the GetLogFont() function.0) Working with Fonts Much of Windows graphical output consists of text in a variety of fonts. These attributes specify the width. a GDI handle (HFONT) also represents font object instances. the font mapper looks for the nearest match of the requested characteristics from the list of installed fonts. The quickest and easiest way to create a font is with CFont's CreatePointFont() function. rendering precision. Fonts and the CFont Class The MFC CFont class is a wrapper for the HFONT GDI object. brushes. and store the details for each instance of a font. initialize. To reduce the overhead of memory and processing time required to load. orientation. Selecting Fonts into the Device Context As with the other GDI objects. After the font is selected. You must ensure that the font is not currently selected in a device context when it is deleted. A much more sophisticated font-creation function is CreateFont(). pitch. weight. which then creates a font and returns a font handle. KCCS Warangal . By R.. escapement. You can initialize the LOGFONT structure with these specifications and pass a pointer to the LOGFONT structure to the CreateFontIndirect() function. a typeface name. The fonts and their related rendering data for each character make a considerable memory footprint for each instance of a font object. Windows uses a font mapper. which lets you specify a huge number of required attributes for the font.

You can find the average widths.93 - . TA_CENTER. and TA_BOTTOM. and many other specific elements of a font from its TEXTMETRICS structure. These structures are full of information about TrueType fonts. You can change the color of the rendered text with the device context's SetTextColor() and SetBkColor() functions to set the foreground and background colors to a specified COLORREF value. You can combine this flag value with the TA_NOUPDATECP and TA_UPDATECP to not update or update the current graphic cursor position after the text rendering. height. TA_RIGHT. KCCS Warangal . By R. The device context's text-alignment flags adjust the position of the text relative to the given coordinate. Thirupathi MCA..0) Stock Fonts A number of stock fonts can be selected with the SelectStockObject() function as. Stock Font Objects Stock Object Flag ANSI_FIXED_FONT ANSI_VAR_FONT SYSTEM_FONT DEVICE_DEFAULT_FONT OEM_FIXED_FONT Font Description ANSI fixed pitch ANSI variable pitch Current Windows system font Device's default font OEM's fixed-pitch font Device Context Font Interrogation Functions The device context has a number of member functions that let you retrieve information regarding the currently selected font. which lets you specify an x and y coordinate and a CString holding the text to display. TA_BASELINE. Lecturer in Computer Science. The device context's GetOutputTextMetrics() function fills such a structure for you with details of the currently selected font. The GetOutlineTextMetrics() function returns an array of OUTLINETEXTMETRICS structures. TA_LEFT. You can use the GetCharWidth() function to fill an array with the widths of individual characters for non-TrueType fonts or GetABCCharWidths() for TrueType fonts.WEB AND VISUAL PROGRAMMING (VC++ 6. Text-Rendering Functions Many text-rendering functions are available that perform slightly different jobs in different circumstances. such as TA_TOP. You can retrieve the typeface name of the currently selected font by calling the GetTextFace() function and passing a CString object by reference to receive the typeface name. You can adjust these flags by using the SetTextAlign() function and passing a combination of the alignment flags. The simplest is TextOut(). You can make the background behind the text transparent or opaque by passing the TRANSPARENT or OPAQUE flag to the SetBkMode() function.

The DrawText() function performs some quite advanced text formatting. and the source bitmap filename from the Bitmap Properties dialog box.EXE or .WEB AND VISUAL PROGRAMMING (VC++ 6. DT_TOP.0) The ExtTextOut() function lets you clip text to a specified rectangle by using the ETO_CLIPPED flag. and DT_CENTER (and many others).94 - . such as word wrapping and justification. GIF. such as DT_WORDBREAK. These bitmaps then are loaded from the current module ready for drawing. Creating a Bitmap Resource with the Resource Editor You can create a new bitmap resource from the Insert Resource dialog box in the Visual Studio Resource Editor. You can pass a combination of formatting flag values. You can supply an array of spacing values to separate the individual character cells to ExtTextOut(). These tabs then are expanded to positions specified by an array of consecutive tab positions relative to a specified origin. as Editing a bitmap resource. DT_RIGHT. a bitmap instance is another low-level GDI object represented by the HBITMAP handle. By R. KCCS Warangal . You then can draw the bitmap using the Resource Editor drawing tools. Before you can use bitmaps in your application. and many other common formats and copy and paste the image into a new bitmap.. you generally create a number of bitmap resources that are bound with your . Creating and Loading Bitmaps Images are used extensively in Windows. Lecturer in Computer Science. You can call the GrayString() function to draw grayed text using a specific graying brush and optionally pass a pointer to your own text-rendering function. the resource ID. JPEG. Thirupathi MCA. You can use TabbedTextout() to display a text string with embedded tab characters. You also can open BMP. DT_LEFT. You can change the size.DLL when linked.

If the bitmap is found and loaded from the executable module. The CreateBitmap() function lets you create a bitmap in memory and specify its width. number of color bits per pixel. you must select the original monochrome bitmap back into the device context before deleting the CBitmap object or calling DeleteObject() to destroy the GDI bitmap object. Bitmap Copying After you select a valid bitmap into a memory-based device context. you must pass a pointer to a valid device context along with a width and height. it is initialized with a monochrome bitmap.WEB AND VISUAL PROGRAMMING (VC++ 6. The CBitmap class is another CgdiObject-derived class. the source coordinates to copy from (relative to the By R.. height. To do this. passing a resource ID (or resource name) that identifies the specific bitmap.0) When you compile the program. You then should select your custom bitmap into the device context and perform the copy into the screen device context. These functions are commonly known as BitBlt functions. BitBlt() lets you specify the source device context (your memory DC). number of bit planes (color planes). and the HBITMAP handle is valid. Creating Bitmaps You can create a bitmap image without an associated resource by using one of the bitmap-creation functions. You should use the CreateCompatibleBitmap() function to create bitmaps that are compatible with specific devices. You can create a compatible CreateCompatibleDC() function. you must load the bitmap resource from the executable file. The CreateBitmapIndirect() function lets you specify these values in a BITMAP structure instead of through parameter settings. and (optionally) an array of short values to initialize the bitmap image. memory device context by using the When a memory device context is created. and it wraps the HBITMAP GDI object handle.95 - . You can load a system stock bitmap with the LoadOEMBitmap() function passing a flag value that loads a few standard bitmaps. Thirupathi MCA. After you finish. KCCS Warangal . the bitmap is bundled into the resulting executable file. Drawing with Bitmaps After you create a GDI bitmap object you can draw with it using a memory device context and then copy it to a destination device context. LoadBitmap() returns a TRUE value. Loading a Bitmap Before you can use a bitmap. You can construct a CBitmap object using its default constructor and then load a specific bitmap by calling its LoadBitmap() function. you can use the BitBlt() device-context function to transfer all or part of the image onto a displaybased (or printer-based) device context. A bitmap is copied to a device using the Bit Block Transfer functions. Lecturer in Computer Science.

pDC->SelectObject(pbmOriginal). &dcMemory.0) memory DC).CreateCompatibleDC(pDC). GetClientRect(rcClient).0.SRCCOPY).96 - .. sizing information. You can change the technique used to copy the image area by passing a flag value to the SetStretchBltMode() function. as well as a destination width and height.rcClient.48. Lecturer in Computer Science. } Creating a Device-Independent Bitmap Class The bitmaps discussed so far are called device-dependent bitmaps because they rely on the current display device context for their palette colors and are dependent on the current display resolution to determine the displayed size. CRect rcClient. void CBitmapdemoView::OnDraw(CDC* pDC) { // Create a compatible memory device context CDC dcMemory. You also can specify a raster operation flag that can be used to invert the image during copying. You can use the MaskBlt() function to perform an image copy from a source device context through the holes in a mask provided by a monochrome bitmap into the destination device context. KCCS Warangal . merge the source with the destination image.0.WEB AND VISUAL PROGRAMMING (VC++ 6.rcClient. CBitmap *pbmOriginal = dcMemory. just copy the source to the destination. and colors. or perform a number of other logical operations between the source and destination during the copy. Then you use StretchBlt() to stretch it so that it fills the view. The image then expands or shrinks to fit the destination width and height. pDC->StretchBlt(0.SelectObject(&bmImage).0. bmImage. The first part of the structure consists of one of the various header structures followed by By R.Height(). Thirupathi MCA.Width(). The following code fragment shows how to create a memory device context. and the width and height describing the area to copy. dcMemory. // Load and select the bitmap resource CBitmap bmImage. This method provides a fast and easy way to perform zoom operations.LoadBitmap(IDB_TSTBITMAP). the destination coordinates (relative to the destination DC). load a re source bitmap. and select it into the memory device context. A device-independent bitmap (DIB) not only stores the bitmap image but also uses a BITMAPINFO structure to store the color depth. The StretchBlt() function lets you specify a source width and height.48.

By using the information about the resolution of the device. KCCS Warangal . you can render the image to the correct size. bits per pixel. and store a DIB. m_pDIB. void InitializeColors(). or by using one of the device-context mapping modes. represented to the best capabilities of various devices while preserving the original size and colors. public: CBitmap m_bmBitmap. The following code fragment shows a class definition for a DIB manipulation class: class CDIB : public CObject { public: CDIB(). You can create a BITMAPINFO and associate it with a bitmap image to form a DIB. Thirupathi MCA. VOID* GetDIBBitArray() const.int x. By R. After you create a DIB. compression technique. Specifying the pixels per meter provides an important piece of information that lets you render the DIB to the correct size of various devices. This section shows some of the steps required to create. Lecturer in Computer Science. height. The sample code builds a DIB class derived from CBitmap to extend the bitmap functionality into a DIB.0) an array of RGBQUAD structures that store the colors used in the bitmap. BOOL CreateDIB(DWORD dwWidth.97 - . After specifying the header details. number of bit planes. private: LPBITMAPINFO }. BOOL CreateDIBFromBitmap(CDC* pDC). you can transfer it onto different machines and display the same image.int nBits). you should initialize the RGBQUAD structures that specify each color used in the bitmap. you first must initialize a BITMAPINFOHEADER structure or one of its more modern counterparts. int GetDIBCols() const.. You can initialize a number of member variables in the DIB header to specify the DIB width. virtual ~CDIB().int y). Creating a DIB To create a DIB. pixels per meter in the x and y dimensions.WEB AND VISUAL PROGRAMMING (VC++ 6. display. BOOL CopyDIB(CDC* pDestDC. such as the BITMAPV5HEADER. and the actual number of colors used. You may want to use the colors from the palette selected in a specific device context by using the SetDIBColorTable() function. This function fills the RGBQUAD array for you from the specified device-context handle.DWORD dwHeight.


You will notice that the class uses a BITMAPINFO pointer (m_pDIB) to the buffer containing the DIB and has an embedded device-dependent bitmap (m_bmBitmap) for transferring the image from an existing bitmap resource. You then could implement the CreateDIB() and associated functions to allocate the memory for a DIB and initialize the BITMAPINFO structure, like this: CDIB::CDIB() : m_pDIB(NULL) { } CDIB::~CDIB() { if (m_pDIB) delete m_pDIB; } BOOL CDIB::CreateDIB(DWORD dwWidth,DWORD dwHeight,int nBits) { if (m_pDIB) return FALSE; const DWORD dwcBihSize = sizeof(BITMAPINFOHEADER); // Calculate the memory required for the DIB DWORD dwSize = dwcBihSize + (2>>nBits) * sizeof(RGBQUAD) + ((nBits * dwWidth) * dwHeight); m_pDIB = (LPBITMAPINFO)new BYTE[dwSize]; if (!m_pDIB) return FALSE; m_pDIB->bmiHeader.biSize = dwcBihSize; m_pDIB->bmiHeader.biWidth = dwWidth; m_pDIB->bmiHeader.biHeight = dwHeight; m_pDIB->bmiHeader.biBitCount = nBits; m_pDIB->bmiHeader.biPlanes = 1; m_pDIB->bmiHeader.biCompression = BI_RGB; m_pDIB->bmiHeader.biXPelsPerMeter = 1000; m_pDIB->bmiHeader.biYPelsPerMeter = 1000; m_pDIB->bmiHeader.biClrUsed = 0; m_pDIB->bmiHeader.biClrImportant = 0; InitializeColors(); return TRUE; } You will notice that dwSize is calculated from the size of the BITMAPINFOHEADER structure, the size of the RGBQUAD array required for the specified color depth, and the size of the resulting bitmap buffer.

By R. Thirupathi MCA., Lecturer in Computer Science, KCCS Warangal
- 98 -


The BITMAPINFOHEADER structure is initialized with dimensions of 1,000x1,000 pixels per meter and uses the specified width, height, and color depth. The compression flag biCompression lets you specify the type of compression used in the DIB image buffer. The BI_RGB flag shown in the code sample indicates that no compression is used. The colors then could be initialized (all to black) like this: void CDIB::InitializeColors() { if (!m_pDIB) return; // This just initializes all colors to black LPRGBQUAD lpColors = (LPRGBQUAD)(m_pDIB+m_pDIB->bmiHeader.biSize); for(int i=0;i<GetDIBCols();i++) { lpColors[i].rgbRed=0; lpColors[i].rgbBlue=0; lpColors[i].rgbGreen=0; lpColors[i].rgbReserved=0; } } You might want to initialize a specific set of RGBQUAD colors, depending on the requirements of your DIB. Creating a DIB from a Device-Dependent Bitmap After you set the color values for the DIB, you can set the pixels for the image directly into a from within your code, or from an existing device-dependent bitmap. Although it is not necessary, it usually is desirable to keep the bitmap image information directly after the BITMAPINFO structure. The following helper functions can help you retrieve the number of colors calculated from the color depth in BITMAPINFOHEADER, a pointer to the bitmap image buffer calculated from the size of the header structure, and the following color value array: int CDIB::GetDIBCols() const { if (!m_pDIB) return 0; return (2>>m_pDIB->bmiHeader.biBitCount); } VOID* CDIB::GetDIBBitArray() const { if (!m_pDIB) return FALSE; return (m_pDIB + m_pDIB->bmiHeader.biSize + GetDIBCols() * sizeof(RGBQUAD)); }

By R. Thirupathi MCA., Lecturer in Computer Science, KCCS Warangal
- 99 -


You can find the size and color-depth information from a device-dependent bitmap by using the CBitmap class's GetBitmap() function. This function fills a BITMAP structure (passed by pointer) with the details about a specific GDI bitmap object. You then can copy these details along with the extra DIB information into the DIB's BITMAPINFOHEADER to create a DIB with the same width, height, and color depth as the device-dependent bitmap. color-value information then can SetDIBColorTable() from a reference device context. The DIB be initialized with the

After the DIB header and color values are initialized from the bitmap, it only remains to copy the image bits themselves. The GetDIBits() function can perform this task for you. You just need to pass the DIB information, a reference device context, and the GDI bitmap handle; GetDIBits() then copies the entire image bitmap into your supplied buffer. If you want to perform the reverse operation of copying a DIB bitmap to a device- dependent bitmap, you can use the corresponding SetDIBits() function. You can even create an HBITMAP GDI object initialized from a DIB directly by using the global CreateDIBitmap() function. The following implementation for the CDIB class's CreateDIBFromBitmap() function demonstrates these functions using the device-dependent m_bmBitmap member. The CreateDIBFromBitmap() function assumes that this CBitmap member was initialized previously through a CreateBitmap() or LoadBitmap(): BOOL CDIB::CreateDIBFromBitmap(CDC* pDC) { if (!pDC) return FALSE; HDC hDC = pDC->GetSafeHdc(); BITMAP bimapInfo; m_bmBitmap.GetBitmap(&bimapInfo); if (!CreateDIB(bimapInfo.bmWidth,bimapInfo.bmHeight, bimapInfo.bmBitsPixel)) return FALSE; LPRGBQUAD lpColors = (LPRGBQUAD)(m_pDIB+m_pDIB->bmiHeader.biSize); SetDIBColorTable(hDC,0,GetDIBCols(),lpColors); // This implicitly assumes that the source bitmap // is at the 1 pixel per mm resolution BOOL bSuccess = (GetDIBits(hDC,(HBITMAP)m_bmBitmap, 0,bimapInfo.bmHeight,GetDIBBitArray(), m_pDIB,DIB_RGB_COLORS) > 0); return bSuccess; }

By R. Thirupathi MCA., Lecturer in Computer Science, KCCS Warangal
- 100 -

You can set this flag to either DIB_RGB_COLORS to indicate that the color values are literal RGB values. x. These functions are similar to the device-dependent blit functions you saw earlier. g_DIB.000 pixelper-meter specification: BOOL CDIB::CopyDIB(CDC* pDestDC. } After calling the CreateDIBFromBitmap() function. Lecturer in Computer Science. The global SetDIBitsToDevice() function copies the image from a DIB buffer directly to a specified device context at a specified position. as well as the width.m_bmBitmap.h" CDIB g_DIB. By R. This function uses StretchDIBits() to render the DIB into a device context that is provided. You can specify the number of lines to copy. Thirupathi MCA. height. BOOL bOK = StretchDIBits(pDestDC->GetSafeHdc()..WEB AND VISUAL PROGRAMMING (VC++ 6. CClientDC dc(this).LoadBitmap(IDB_TSTBITMAP).0) You will notice the DIB_RGB_COLORS flag also is passed to the GetDIBits() function. or DIB_RGB_PAL to specify color index positions in the device context's current palette.y.CreateDIBFromBitmap(&dc). g_DIB. and position of the source DIB image. You might call the CreateDIBFromBitmap() function after loading a resource-based bitmap like this: #include "dib. The coordinates specified in the destination width and height should be multiplied by 10 so that each DIB pixel represents 1 mm to maintain the 1.int y) { if (!m_pDIB || !pDestDC) return FALSE. the embedded DIB will be initialized in the memory pointed at by the m_pDIB pointer. int nOldMapMode = pDestDC->SetMapMode(MM_LOMETRIC).101 - .int x. This function often is useful when you are trying to preserve the original bitmap size. void CBitmapdemoView::OnInitialUpdate() { CView::OnInitialUpdate(). KCCS Warangal . SetDIBitsToDevice() returns the number of scan lines copied. You can use StretchDIBits() in a way similar to StretchBlt() to stretch the DIB bitmap to the required size. The following example shows an implementation of the CopyDIB() function for the CDIB class defined previously. If the operation succeeds. Drawing with a DIB You can use several GDI functions to draw from a DIB directly into a normal device context.

however. so they should print the image to the correct size. KCCS Warangal . m_pDIB->bmiHeader.-50). CPrintInfo* pInfo) { g_DIB.0) m_pDIB->bmiHeader.50. // Source Width m_pDIB->bmiHeader. return bOK. } void CBitmapdemoView::OnDraw(CDC* pDC) { g_DIB. // Dest Height 0. // Source Height GetDIBBitArray(). } You could invoke this code from your application's view class in the OnDraw() and OnPrint() functions. the DIB should be rendered to the same size and with the same colors to the best capabilities of the device. By R.SRCCOPY) > 0.biHeight. like this: void CBitmapdemoView::OnPrint(CDC* pDC. Thirupathi MCA.m_pDIB. Printer device contexts provide very accurate physical unit mapping.-50).biWidth.CopyDIB(pDC.WEB AND VISUAL PROGRAMMING (VC++ 6. } Regardless of the device context passed to CopyDIB() and the ultimate destination device. Lecturer in Computer Science. // Dest Width m_pDIB->bmiHeader.DIB_RGB_COLORS.102 - .biHeight * -10.0. after previously creating the DIB from the loaded bitmap resource..biWidth * 10.CopyDIB(pDC. pDestDC->SetMapMode(nOldMapMode).50.

After a thread begins to run. and a thread with higher priority becomes runnable (for example. When a thread is prevented from running because its priority is lower than other threads in the system. Thirupathi MCA. When the process is started. it never runs in the context of another process. and the higher-priority thread begins executing. A higher-priority thread becomes runnable. For example. known as a quantum. it is said to be starved. resources. A thread always is associated with a particular process—after the thread is started. and Synchronization A process is started by the operating system when an application is launched. Threads that run at lower priorities occasionally are given a "boost" in their priority in order to prevent deadlock. it's not uncommon for more complex applications to use multiple threads over the lifetime of the process. and threads of execution that are associated with a running instance of an executable program. the simple act of reading and writing to a global variable must be synchronized properly. Threads are scheduled according to their priority.WEB AND VISUAL PROGRAMMING (VC++ 6. Within a particular priority level.0) Manipulating threads and managing processes Win32 Processes. If a low-priority thread is running. because a resource becomes available). The ready state indicates that the thread is capable of running but is waiting to be scheduled to run. Consider this innocent-looking code fragment: int g_nQueuedRequests = 0. one thread is initially associated with that process. Understanding Threads A thread is the smallest schedulable unit of execution in a Windows application.. As long as one thread continues to be associated with the process. threads are scheduled in a circular (or round-robin) fashion. The process owns the memory. it continues to run until one of the following actions occur: The thread exceeds its maximum execution time. If a thread exceeds its quantum. the process continues to run. The thread with the highest priority level is always running. The Need for Synchronization After you introduce multiple threads into an application. the thread is placed in the waiting state. the lower-priority thread immediately is interrupted.103 - . void QueueRequest(void) By R. Threads. KCCS Warangal . A maximum of one thread per system processor is allowed to be in the running state—all other threads are either waiting or are marked as ready. you must plan for problems that simply don't exist in single-threaded programming. Lecturer in Computer Science. and the operating system schedules a new thread to run. Although many simple applications use only a single thread. The running thread yields by waiting for an event or object.

DoSomethingToHandleRequestFromQueue() } This fragment contains two functions that write to the same variable. a fault definitely will occur. InterlockedExchangeAdd increments the value of a 32-bit variable by a specified amount and returns the previous value. InterlockedCompareExchange conditionally sets the value of a 32-bit variable to a new value and returns the previous value. In 64-bit versions of Windows 2000. Because several machine instructions are required to update the value of a variable. it is possible for a thread to be interrupted in the middle of modifying the value of a variable. Lecturer in Computer Science.WEB AND VISUAL PROGRAMMING (VC++ 6. If it's possible for multiple threads to update a variable. Variables passed to these functions must be aligned on 32-bit boundaries. Two basic scenarios exist: On multiprocessor machines. InterlockedCompareExchangePointer conditionally sets the value of a 32-bit variable to a new value and returns the previous value. allowing another thread to corrupt it. even when used with multiple processors: InterlockedIncrement increments a 32-bit variable and returns the new value. it's possible for two or more processors to attempt to access the variable at exactly the same time. InterlockedExchange changes the value of a 32-bit variable to a new value and returns the previous value. Thirupathi MCA. the parameters to this function are 64-bit values. multiple threads don't actually execute at the same time—they only appear to do so.. The following Win32 functions are guaranteed to be atomic and thread safe. which would cause the value for the variable to be corrupted. KCCS Warangal . In a multithreaded application. On uniprocessor machines. you must provide some sort of synchronization for access. InterlockedDecrement decrements a 32-bit variable and returns its value. ++g_nQueuedRequests. By R. It is possible for a thread to be interrupted at any time. it would be very easy to have two threads attempt to modify the variable simultaneously. If your code does not use synchronization primitives from the operating system. In 64-bit versions of Windows 2000. the parameters to this function are 64-bit values. InterlockedExchangePointer changes the value of a 32-bit variable to a new value and returns the previous value.0) { } void SatisfyRequest(void) { —g_nQueuedRequests. DoSomethingToQueueRequest().104 - . The simplest types of synchronization primitives are used to manipulate or test the values of 32-bit scalar variables.

If two threads access the same CString object at exactly the same time. which you can set up in the C/C++ | Code Generation page of the Project Settings dialog box. without interfacing with the user. MFC adds a message pump to these threads. In addition. Because of this. you create a user-interface thread. providing a message loop that is separate from the main message loop of your application's CWinApp object. in the section. CWinApp is itself a prime example of a user-interface thread.. If you will be using MFC objects in your threads.WEB AND VISUAL PROGRAMMING (VC++ 6. although threads share the same memory space. Threads that are created without using a CWinThread object will not properly initialize the internal variables that MFC needs to work with multiple threads. Thirupathi MCA. "Using User-Interface Threads. you use what MFC calls a worker thread. If. MFC Objects and Threads When an application has multiple threads running at the same priority level. on the other hand. ways around this that you will look at later. KCCS Warangal . this means that a thread may access only handle-based MFC objects created in that thread. There are." Types of Threads MFC implements two types of threads. If you are interested in creating a thread that simply goes off on its own and does something. your application already is set up to handle multiple threads. Although both types use the same underlying Win32 API thread mechanisms and both use CWinThread. the order in which they are executed is somewhat random. you want to create a thread that deals with parts of a user interface. such as background calculations. as you will see here. Just as MFC derives CWinApp from CWinThread. they do not share the same structures that MFC uses to map C++ objects to Windows handles. because a call to the AfxBeginThread() function creates one for you.105 - . however. you create your own class derived from CWinThread to implement user-interface threads. Worker threads also are useful when you need to By R. but you do not need to explicitly create a CWinThread object. In general. you have to be certain to link with the multithreaded libraries. These threads are based on CWinThread. they are different in the way that MFC adds functionality to the thread.0) Using Multiple Threads in Your Application If you have created an MFC application with AppWizard. you must create the thread by using the CWinThread class. If not. Using Worker Threads MFC creation benefits Worker threads are handy for any time you want to do something such as calculations or background printing. Actually. Lecturer in Computer Science. because it is derived from CWinThread. you must take special care to ensure that two different threads are not attempting to modify certain objects at the same time.

Although you may choose to create your own CWinThread-based class. AfxBeginThread() returns a pointer to the newly created CWinThread object. Each thread also may have its own priority. or until you call AfxEndThread() from within the thread. it creates a new CWinThread object for you and calls its CreateThread() member function. unless you have specified CREATE_SUSPENDED.106 - . squirrel this away somewhere so that you can work with the member functions of CWinThread later. By R. Optionally. KCCS Warangal . you may specify the CREATE_SUSPENDED flag in the dwCreateFlags parameter to create a thread that is suspended upon creation. This function is overloaded to handle the creation of the two flavors of threads. int nPriority = THREAD_PRIORITY_NORMAL. DWORD dwCreateFlags = 0. you probably will want your thread to start doing its thing right off the bat. The new thread continues to execute the function specified until that function returns. At this point. this is a pointer to a data structure of some sort.WEB AND VISUAL PROGRAMMING (VC++ 6. Because each thread executes independently. The size of the stack may be specified in the call to AfxBeginThread(). which is discussed later. whether a worker or user-interface thread. LPVOID pParam. Creating a worker thread is relatively simple. and the thread that called AfxBeginThread() goes on its merry way. The thread also terminates if the process it is running in terminates. it must have its own stack to keep track of function calls and the like. without forcing the user to wait. However. Starting the Thread An MFC thread. such as receiving data from another application. you may specify a SECURITY_ATTRIBUTES structure to specify security parameters to be used with the thread. Here is the prototype for this function: CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc. let's look at the variety used to create worker threads. In most cases.0) wait on an event to occur. but for now.. LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL ). This thread will not begin executing until ResumeThread() is called. To get a worker thread up and running. is started with a call to AfxBeginThread(). As you will soon see. Lecturer in Computer Science. This parameter may be set to any of the values accepted by SetThreadPriority(). Let's face it—most users are not known for their patience. You When you call AfxBeginThread(). your new thread begins to execute the function you specified. The first parameter is a pointer to the function that will run inside the thread. Thirupathi MCA. this function can take a single parameter. this is not necessary for worker threads. you implement a function that will be run in the thread. UINT nStackSize = 0. Generally. which is passed as the second parameter. and then create the thread with AfxBeginThread().

You can get around this in one of two ways. Lecturer in Computer Science. as Microsoft calls it in its documentation. Accessing a Thread's Return Code The exit code specified when the function returns or calls AfxEndThread() may be accessed by other threads in your application with a call to ::GetExitCodeThread(). pMySecretString). this function starts. In either case. The sole purpose in life for a worker thread is to run its thread function. All thread functions take a single 32-bit argument.WEB AND VISUAL PROGRAMMING (VC++ 6. In general. the thread dies. its stack and other resources are deallocated. or controlling function. which prevents MFC from deleting the object automatically. You could use the following simple thread function to encrypt a string.107 - . so it should be no problem to pass this to ::GetExitCodeThread(). for example: UINT MyThreadProc(LPVOID pParam) { if(pParam == NULL) AfxEndThread(MY_NULL_POINTER_ERROR). your thread function should have a prototype that looks like this: UINT MyThreadProc(LPVOID pParam). the CWinThread object is deleted as soon as the function returns or calls AfxEndThread(). This structure also may be used to return information to the rest of your application. The handle to the thread is contained in the m_hThread member of CWinThread. } You could use this function in a thread created like this: AfxBeginThread(MyThreadProc. when the thread starts.0) Implementing a Thread Function The sole purpose in life for a worker bee is to make honey. while(*pStr) *pStr++ ^= 0xA5. and the CWinThread object is deleted. Thirupathi MCA. or it finishes with the string. whether the function calls AfxEndThread() or simply returns. char *pStr = (char *)pParam. return 0. Although you could pass a single value here. You then can access the By R. After the thread is created. When the function dies. the function stops executing. it generally is more useful to pass a pointer to a structure or other object that can hold more information. such as an int. you can set the m_bAutoDelete member of CWinThread to FALSE. it starts executing until it either discovers that the pointer passed to it is null.. First. First. Catch: By default. KCCS Warangal .

stack size. You also need to make sure that you use the DECLARE_DYNCREATE and IMPLEMENT_DYNCREATE macros in the declaration and implementation of your thread class. KCCS Warangal . MFC creates this for you with the RUNTIME_CLASS macro: AfxBeginThread(RUNTIME_CLASS(CMyThread)). however. Lecturer in Computer Science. The class you derive from CWinThread must include its own override for InitInstance(). The only way to be absolutely certain of this is to specify CREATE_SUSPENDED when the thread is created. as well as the CREATE_SUSPENDED flag for the new thread in the call to AfxBeginThread(). copy the handle. Initializing New Threads Whenever a new thread is created from your thread class by calling AfxBeginThread(). is return TRUE so that MFC knows the initialization succeeded and that it should proceed. The exit code value returned by GetExitCodeThread() contains STILL_ACTIVE if the thread is still running. you now are responsible for deleting the CWinThread object. use this: (CMyThread*) pMyThread = (CMyThread*) AfxBeginThread(RUNTIME_CLASS(CMyThread)). This is the one function that you must override in your thread class. If you want to keep track of the MFC object for your thread. you use a slightly different version of the AfxBeginThread() function. and security attributes. the return code that the thread passed when it returned or called AfxEndThread(). Creating the Thread To create a user-interface thread.. because they use the same mechanisms provided by the operating system to manage the new thread. However. MFC calls the InitInstance() function of your thread class. DuplicateHandle(): It is used to create a copy of the m_hThread member after the thread is created. Keeping a pointer to the MFC thread object enables you to access the member data and functions of your thread class from other threads. but you may choose whether to override several other functions or use the defaults provided by CWinThread. Creating a Thread Class You derive your own class from CWinThread to create an MFC user-interface thread. The version used to create user-interface threads takes a pointer to a CRuntimeClass object for your thread class.108 - .WEB AND VISUAL PROGRAMMING (VC++ 6. or if the thread has terminated. All that your InitInstance() function really must do. then call ResumeThread() to start the thread. You may specify a priority. Using User-Interface Threads User-interface threads are similar to worker threads. Thirupathi MCA. If something By R.0) m_hThread member after the thread terminates.

You can override the OnIdle() member to perform tasks when the message queue is empty. If you have allocated memory in your InitInstance() function. You then should set the m_pMainWnd member of CWinThread to a pointer to the window you have created. which have the command ID WM_USER+1. you also should override the ExitInstance() member of CWinThread in your thread class. In this case. You may override the PreTranslateMessage() function if you want to intercept messages before the message pump dispatches them. To then handle the message you posted. KCCS Warangal . including cases where InitInstance() returns FALSE.the ClassWizard will add and remove mapping macros here. } By R. to handle messages that are sent directly to the thread rather than to a given window.. HandleThreadMessage) END_MESSAGE_MAP() This message map results in messages being sent directly to your thread. The default implementation handles only those exceptions caused by the WM_CREATE or WM_PAINT messages.WEB AND VISUAL PROGRAMMING (VC++ 6. You can override this function to do anything else you want your thread to do. which takes an additional parameter—the thread identifier. you should return FALSE. although most user-interface threads will simply use the default implementation of CWinThread::Run(). This example uses WM_USER+1. Handling Messages in Threads The default implementation of CWinThread::Run() provides a message pump for your new thread.0) goes wrong in InitInstance(). //} } AFX_MSG_MAP ON_THREAD_MESSAGE(WM_USER+1. Lecturer in Computer Science. which enables the message dispatch system of CWinThread to manage messages from this window exclusively. You can send messages directly to a thread with CwinThread::PostThreadMessage(). You also may use a special message map macro. the message map for your thread would look something like this: BEGIN_MESSAGE_MAP(CMyThread. This is similar to the ::PostThreadMessage() API call.109 - . LPARAM lParam) { PostQuitMessage(MY_THREAD_RECEIVED_END_MESSAGE). to be handled by the HandleThreadMessage() member of your thread class. ON_THREAD_MESSAGE. myLParam). myWParam. as shown here: pMyThread->PostThreadMessage(WM_USER+1. This is called whenever your thread terminates. execution of the thread stops and the thread is destroyed. such as memory-allocation failures. The handler for your thread message looks like this: afx_msg void CMyThread::HandleThreadMessage(WPARAM wParam. CWinThread) //{ { AFX_MSG_MAP(CMyThread) // NOTE . Thirupathi MCA. which gives a valid user-defined message ID.

By R. Synchronization objects are a collection of system-supplied objects that allow threads to communicate with one another. For user-interface threads. and events. you can use critical sections to ensure that only one thread can access certain pieces of code at the same time. Thread Synchronization Synchronization objects are a very important aspect of thread programming.WEB AND VISUAL PROGRAMMING (VC++ 6. you easily could allocate memory within a thread and store the pointer in a variable local to the thread function of a worker thread or a member of your CWinThread class. Lecturer in Computer Science. For the threads created here. if your user-interface thread manages an MFC window. without any provisions for cleaning up allocated memory. it is crucial that you understand them. and you want to create a new thread for each connection. To use MFC's critical sections. More important. a thread ends when the thread function it is running returns. you generally don't deal with the thread function directly. this process is pretty straightforward. If you need to terminate a thread from outside that thread. variables local to the thread function are thread local. The Win32 API provides the TerminateThread() function. There are four such objects in Windows: critical sections. Thread Local Storage In some cases. Likewise. You may be developing a dynamic link library (DLL). Thirupathi MCA. For worker threads.0) Terminating Threads A thread can terminate in several ways. try to use some form of communication to tell the thread to terminate itself gracefully. as set in the m_pMainWnd member. MFC calls PostQuitMessage() for you when the main window is destroyed. Normally. KCCS Warangal . CCriticalSection In places where you know that your threads will be dealing with things that only one thread at a time should be accessing. you first need to create a CCriticalSection object. and each thread requires its own dynamic storage. that handles connections to outside processes. semaphores. the thread that is terminated in this way may be interrupted in the middle of several different transactions. Because threads have their own stack. for example. this step is trivial. In either case. an instance of CWinThread has its own set of data members that are thread local.. user-interface threads call ExitInstance() before actually terminating. you use several different threads running the same thread function. mutexes. Because the constructor takes no arguments. however. Providing for storage on a thread-by-thread basis is generally necessary only if you are developing libraries that may be called by multiple threads. TerminateThread() stops the thread dead in its tracks.110 - .

however. this: First. making certain to use the same name in the call to the constructor. CCriticalSection provides a simple. Finally. such as CMutex. By R.. as well as the CMutex object. First. Second. LPSECURITY_ATTRIBUTES lpsaAttribute = NULL ).WEB AND VISUAL PROGRAMMING (VC++ 6. it does have its limitations. For this. before a thread in your application needs to enter a critical section of the code. In cases like this. you can initialize the mutex and lock it while the protected data is initialized. you can unlock the mutex when it is safe for other threads to start accessing the data. KCCS Warangal . it should call the Lock() member of your CCriticalSection object. the performance advantage gained with critical sections tends to be reduced when many threads are contending for a single critical section. allowing other threads to access the critical section. It is your responsibility to correctly and consistently use critical sections to control access to all data that might be corrupted by simultaneous access by multiple threads. CCriticalSection objects are valid only within a process. If a second thread tries to lock the same critical section object. using the CCriticalSection object is purely voluntary on the part of the developer. critical sections incur slight additional overhead when used on multiprocessor machines. It often is useful to declare a mutex object as a member of a class representing data that needs to be protected from simultaneous access by multiple threads. Like critical sections. LPCTSTR lpszName = NULL. The first parameter enables you to specify the ownership of the mutex when it is created. Also. The prototype for its constructor looks like CMutex( BOOL bInitiallyOwn = FALSE. Only one thread may own a given mutex at a given time. the Lock() call blocks the thread until the critical section is available. To share a mutex between two processes. This occurs when the first thread calls Unlock(). CMutex The MFC CMutex class is similar to CCriticalSection in that you can use it to provide mutually exclusive access to certain sections of your code. If you don't use the critical section properly. although you can use them between different processes. Lecturer in Computer Science.111 - . you should create a CMutex object in each process. you cannot use them to protect memory or other resources shared between processes. except that Lock() uses the timeout value passed as a parameter. you need to use one of the beefier classes. lightweight mechanism to limit access to critical sections in your code. then. CMutex objects work to protect your data only if you use them. Thirupathi MCA. it won't do anything to protect your data. you create a CMutex object. all others will block on a call to Lock() until the owning thread releases ownership.0) Next. You use the Lock() and Unlock() functions in much the same way you use the calls for critical sections. The first thread to call the constructor actually creates the operating system mutex.

KCCS Warangal .0) The next thread to call CMutex() creates a CMutex object corresponding to the mutex object that already was created with the same name CSemaphore Semaphore objects are similar to mutexes. Lecturer in Computer Science. The pstrName and lpsaAttributes parameters work just as they did in CMutex. LPCTSTR lpszName = NULL. threads requesting access have to wait until a thread releases the semaphore. this count is decremented. LPSECURITY_ATTRIBUTES lpsaAttributes = NULL ). and then set it to signaled when an event occurs. The prototype of the constructor for CSemaphore objects looks like this: CSemaphore( LONG lInitialCount = 1. This is very similar to the constructor for the other CSyncObject-derived objects you have seen so far. LPSECURITY_ATTRIBUTES lpsaAttribute = NULL ). which MFC encapsulates in the CEvent class. The Lock() and Unlock() functions of CSemaphore work the same as those for CMutex. thereby increment ing the semaphore count. except instead of providing access to a single thread. Win32 provides the aptly named event object. occasionally. An event object is always in one of two states: signaled or unsignaled (or set or reset). The parameters passed to the constructor include a name for By R. LONG lMaxCount = 1. The default values of 1 and 1 create a semaphore that is essentially the same as a mutex. you may create semaphores that allow access only to a limited number of threads simultaneously.WEB AND VISUAL PROGRAMMING (VC++ 6. To allow you to signal events. BOOL bManualReset = FALSE. Semaphores are based on a counter that they keep. you will want your program to wait for some event to occur instead of waiting for a resource to become available. as well as a maximum value for the counter.. These parameters specify an initial value for the semaphore's counter. and CMutex allows only one. LPCTSTR pstrName = NULL. Creation of a CEvent object begins with a call to its constructor: CEvent( BOOL bInitiallyOwn = FALSE. except that CSemaphore may allow a fixed number of concurrent accesses. CEvent Although the previous synchronization objects provide a method of protecting various resources or sections of your code. You need to modify these parameters when the semaphore is created to allow more than one thread to have access to the semaphore. It is common to create an event object in its unsignaled state. but you have not seen the first two parameters before. Thirupathi MCA.112 - . This method is useful when waiting to receive packets from a network or waiting for a thread to signal that it has completed some task. because only one thread may be granted access to the semaphore at any one time. If the count is 0. When a thread is granted access to the semaphore.

and a pointer to a security attributes structure. the event is set to signaled on creation.WEB AND VISUAL PROGRAMMING (VC++ 6. if TRUE. CreateProcess() also takes 27 other parameters. If the wait times out. As you can with other CSyncObjects.0) the object. To do this. Lecturer in Computer Science. however. Thirupathi MCA. you can use CreateProcess(). which may be used by other processes. Lock() returns TRUE. CreateProcess() takes a filename for an executable file that will be run in the new process. Lock() returns FALSE. you will be relieved to know that most of the parameters to CreateProcess() have reasonable default values. you may want to create new processes that include their own memory space and are independent of the process that created them. the event initially is unsignaled. Although an event is not really owned by any one thread (as a mutex is). Because CreateProcess() seldom is used by the majority of Win32 applications. you won't look at the details of it here. however. By R. which enables you to specify a timeout value.113 - . either directly or indirectly. If the event is signaled before the timeout. If you do need to do this. KCCS Warangal . Creating a New Process In some very large applications. If this value is FALSE. you can wait on an event with the Lock() member.. the bInitiallyOwn parameter enables you to set the initial value of the event.

114 - . Lecturer in Computer Science.0) UNIT-IV SYSTEM REGISTRY & EXCEPTION HANDLING By R. Thirupathi MCA. KCCS Warangal .WEB AND VISUAL PROGRAMMING (VC++ 6..

like the directories on your hard disk. 2. 5.this branch contains all of your file types as well as OLE information for all your OLE-aware applications.this branch contains information about all of the hardware and software installed on your computer. Binary. HKEY_CLASSES_ROOT .WEB AND VISUAL PROGRAMMING (VC++ 6. 3. Thirupathi MCA. for use with Windows' Plug-&-Play subsystem. this value is defined as REG_DWORD in the Windows header files. There are six main branches (five in Windows 2000 and Windows XP). There are three types of values. the default branch here contains the currently-logged in user. Windows is designed to run on little-endian computer architectures.the use of these depends upon the context. Each value contains the actual information stored in the Registry. the default branch here contains a template to be used for newly-added users. The following registry value types are defined in Winnt. Registry Value Types A registry value can store data in various formats. and DWORD . They are as follows: 1. KCCS Warangal . Therefore.115 - . HKEY_USERS .0) Structure of the Registry The Registry has a hierarchal structure. 6. each containing a specific portion of the information stored in the Registry. In Windows 2000/XP. HKEY_CURRENT_USER . When you store data under a registry value. for instance by calling the RegSetValueEx function.. In Windows 95/98/Me. Each key can contain other keys.this branch points to the part of HKEY_LOCAL_MACHINE appropriate for the current hardware configuration. String. HKEY_DYN_DATA (Windows 95/98/Me only) . REG_DWORD_LITTLE_ENDIAN A 32-bit number in little-endian format. you can specify one of the following values to indicate the type of data being stored. see below) is called a Key. the current hardware configuration is specified in HKEY_CURRENT_CONFIG. as well as Values.this branch points to the part of HKEY_LOCAL_MACHINE. HKEY_CURRENT_CONFIG . Lecturer in Computer Science. 4.h. Each branch (denoted by a folder icon in the Registry Editor. By R. HKEY_LOCAL_MACHINE . A 32-bit number.this branch points to the part of HKEY_USERS appropriate for the current user. Value REG_BINARY REG_DWORD Type Binary data in any form. Since you can specify multiple hardware configurations.this branch contains certain preferences (such as colors and control panel settings) for each of the users of the computer.

Thirupathi MCA.. then click OK. REG_EXPAND_SZ REG_LINK REG_MULTI_SZ REG_NONE REG_QWORD REG_QWORD_LITTLE_ENDIAN A 64-bit number in little-endian format. terminated by an empty string (\0). The following is an example: String1\0String2\0String3\0LastString\0\0 The first \0 terminates the first string. To expand the environment variable references. This will be either a Unicode or an ANSI string. Editing the Registry Manually Editing the computer's registry begins with a program on the computer called "regedit". KCCS Warangal . This program is started by clicking the Start button then "Run". "%PATH%"). By R. A sequence of null-terminated strings. Some UNIX systems support big-endian architectures. Lecturer in Computer Science.WEB AND VISUAL PROGRAMMING (VC++ 6. Type regedit into the text field. Note that the final terminator must be factored into the length of the string. REG_SZ A null-terminated string. It will be a Unicode or ANSI string depending on whether you use the Unicode or ANSI functions. use the ExpandEnvironmentStrings function. A 64-bit number. the second to the last \0 terminates the last string. Therefore.0) REG_DWORD_BIG_ENDIAN A 32-bit number in big-endian format. Windows is designed to run on little-endian computer architectures. No defined value type. depending on whether you use the Unicode or ANSI functions. and the final \0 terminates the sequence. this value is defined as REG_QWORD in the Windows header files. A null-terminated string that contains unexpanded references to environment variables (for example. A null-terminated Unicode string that contains the target path of a symbolic link that was created by calling the RegCreateKeyEx function with REG_OPTION_CREATE_LINK.116 - .

Thirupathi MCA. Lecturer in Computer Science. KCCS Warangal . Click the to the left of HKEY_CURRENT_USER.0) You will see this: NOTE: There is a HKEY_CURRENT_USER for each profile on Windows 2000 and Windows XP. You will want to examine each one. In order to do that. you will need to log into each profile and examine this key.117 - .. By R.WEB AND VISUAL PROGRAMMING (VC++ 6.

WEB AND VISUAL PROGRAMMING (VC++ 6. KCCS Warangal .0) Click the to the left of Software Click the to the left of Microsoft Click the to the left of Windows By R.. Thirupathi MCA. Lecturer in Computer Science.118 - .


Click the to the left of CurrentVersion

Click on the Run folder so that it highlights in blue. The window to the right in the registry is the contents of the Run folder. This is what we want to examine. You may find only a few things in here. Or you may find so much that you have to scroll down to see it all. Now is the time to analyze what is in here. Proceed to the next step.

There are a few good ways to understand what things are in here. There are also a few good tips to recognize the bad stuff right away and blow it out of there. What you find in here will fit into a few categories:

By R. Thirupathi MCA., Lecturer in Computer Science, KCCS Warangal
- 119 -


HKEY_LOCAL_MACHINE This key contains the global information about the system that pertains to system hardware and application software settings. The information contained therein applies to all users who log into the system in Windows 95/98 and Windows NT. This key has three aliases at the top level: The first-level subkeys of HKEY_LOCAL_MACHINE for Windows NT are:
7. HARDWARE – This contains detailed information about the system’s hardware

configuration and locally attached devices, such as SCSI peripherals.

8. SAM – This subkey is a placeholder for the security accounts manager. 9. SECURITY – This is a placeholder for application security information. 10. SOFTWARE – This subkey contains a complete range of information about

installed applications.
11. SYSTEM – This contains detailed information about the CurrentControlSet, as

well as the previously configured Control Sets. HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Sr This key is related to the System Restore filter. This key and its values must not be be modified under any circumstances as any modifications can cause the operating system to malfunction. HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Srservice This key is related to the System Restore service. This key and its values must not be be modified under any circumstances as any modifications can cause the operating system to malfunction. HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\CurrentVersion\S ystemRestore In this registry key, you can modify some DWORD values. However, in this key, there are some values that must not be modified under any circumstances. HKEY_CLASSES_ROOT This is the alias for HKEY_LOCAL_MACHINE\Software\Classes, and contains information that deals with file associations, drag-and-drop, shortcuts, and OLE/COM. This applies to Windows NT 4 and Windows 95/98. HKEY_USERS This key contains information specific to each user configured on the system. Windows NT 4 requires user accounts, and will have a \.Default subkey along with a subkey identified by a Security ID code (SID) for each user. Windows 95 and 98 can contain only a \.Default subkey or specific user keys, which are not encrypted like the Security ID keys in Windows NT 4.

By R. Thirupathi MCA., Lecturer in Computer Science, KCCS Warangal
- 120 -


HKEY_CURRENT_USER It is an alias for the HKEY_USERS\Whatever user you logged in as. This applies to Windows 95/98 and Windows NT 4. In Windows 95 and 98, if the system logon screen is canceled or nonexistent, the key will use the \.Default key. The first two subkeys of HKEY_USERS for Windows 95 and 98 (there may be more depending on your system configuration) are:
12. .Default – This contains the default user configuration information. 13. USERNAME (substitute the user name) – This subkey contains the

configuration for that specific user. Both keys contain the following subkeys:
14. AppEvents – This contains pointers to the sounds made by Windows 95 and

98 when an event occurs as well as configuration information for the desktop themes.
15. Control Panel – This subkey contains the settings for some of the Control

Panel applets. The settings stored here were previously stored in the Windows 3.x WIN.INI file, and some of them have been moved to the registry. Other settings remain in .INI files and are used by legacy applications.
16. InstallLocationsMRU

– The Most Recently installation is stored here in this subkey. the Current Control Set.





17. Keyboard layout – This subkey identifies the keyboard layout as specified in 18. Network – This contains a list of subkeys that identify the current network

connections (those defined as persistent), and a most recently used list.
19. RemoteAccess – This subkey contains the addresses and profiles for the

installed Dial-Up Networking configurations.
20. Software – This subkey contains the individual settings for each users

software configuration The Registry and INI files While .INI files haven’t gone away (a quick scan of the system I’m writing this on shows more than 150 of them), they are primarily of the private INI file variety. That is, they’re installed by, and related to, specific applications. You’ll also find the WIN.INI and SYSTEM.INI still exist, and, as a point of fact, are necessary for compatibility with older, 16-bit, applications

writing application, programs that manipulate the registry.
Registry Key Creation using RegCreateKey: The Registry keys can be created under any other keys except at the root level. One more point to be noted is applications cannot create entries directly under HKEY_USERS and HKEY_LOCAL_MACHINE. The sample code for creating a registry key is as follows.

By R. Thirupathi MCA., Lecturer in Computer Science, KCCS Warangal
- 121 -

Creating and Modifying values: There are two types of values which might need to be modified.(CONST BYTE*) &dwVal.NULL. A sample implementation for RegSetValueEx is as follows. REG_DWORD. DWORD Variable name. &hKey. sizeof(DWORD)). LONG iSuccess = RegCreateKeyEx( HKEY_CURRENT_USER. LPDWORD lpdwDisp = &dwDisp. l_strDWordSample. if(iSuccess == ERROR_SUCCESS) { RegCloseKey(hKey). l_strExampleKey. KEY_ALL_ACCESS. DWORD dwVal = 100. One is creating and setting the value for a REG_DWORD entry and the next is creating and setting the value of REG_SZ entry. LONG iSuccess = RegCreateKeyEx( HKEY_CURRENT_USER.0) HKEY hKey.. REG_OPTION_NON_VOLATILE. CString l_strDWordSample = "DWORDSample". REG_OPTION_NON_VOLATILE. if(iSuccess == ERROR_SUCCESS) { RegSetValueEx (hKey. By R.REG_SZ entries using RegSetValueEx: The following is the sample code for setting a REG_SZ entry. Registry Values . This function takes parameters of the Handle to the Registry Key. &hKey.lpdwDisp). DWORD dwDisp = 0. } The above piece of code will create an entry under HKEY_CURRENT_USER\Software\TestKey. Thirupathi MCA. } Now the REG_DWORD variable Registry Values . HKEY hKey. Lecturer in Computer Science. We use the same key entry for this also.. Registry Values .lpdwDisp).122 - . DWORD value etc. NULL. LPDWORD lpdwDisp = &dwDisp. 0L.REG_DWORD entries using RegSetValueEx: This is achieved by using the function RegSetValueEx. CString l_strExampleKey = "SOFTWARE\\Microsoft\\Exchange\\MSExchangeAdminCommon". 0L. DWORD dwDisp = 0. l_strExampleKey. KEY_ALL_ACCESS.WEB AND VISUAL PROGRAMMING (VC++ 6. KCCS Warangal . CString l_strExampleKey = "SOFTWARE\\TestKey". 0L.NULL. NULL.

LPDWORD lpdwDisp = &dwDisp. DWORD dwDisp = 0.123 - . } You can modify registry data while (in an MSI project) filtering the view by a specific component or with the All Application Data option. Lecturer in Computer Science. KCCS Warangal . NULL. 0L. (LPBYTE) l_strStringSampleVal. CString l_strExampleKey = "SOFTWARE\\Microsoft\\Exchange\\MSExchangeAdminCommon". l_strStringSample.lpdwDisp). LONG iSuccess = RegCreateKeyEx( HKEY_CURRENT_USER.. Enter a new value or edit the existing value in the resulting dialog. Each new key in the InstallShield Registry editor has an empty default string value.NULL. l_strStringSampleVal = "String Value"..0) HKEY hKey. l_strStringSampleVal. REG_OPTION_NON_VOLATILE.GetBuffer(l_strStringSampleVal. To modify this or any value data: • • • Right-click on a value name and select modify or double-click the string in the destination view. REG_SZ.WEB AND VISUAL PROGRAMMING (VC++ 6. 0. l_strExampleKey.GetLength()). &hKey. By R. Thirupathi MCA. if(iSuccess == ERROR_SUCCESS) { RegSetValueEx(hKey.GetLength()+ 1). KEY_ALL_ACCESS. Click OK. CString l_strStringSample = "StringSample".

Thirupathi MCA. when dealing with an older program using MFC exception macros. TRY You use this macro to set up a TRY block.0 did not support the C++ exception mechanism. Here is a list of the MFC exception macros: THROW THROW_LAST TRY CATCH AND_CATCH AND_CATCH_ALL END_CATCH END_CATCH_ALL THROW This macro throws the exception to the CATCH block. Usually when an exception that was just caught is thrown. By R. control is passed to an MFC library module to print an error message and exit. program control goes to the CATCH block. Better yet. and throw. the C++ exception keyword equivalents are try. If a CATCH block is specified.WEB AND VISUAL PROGRAMMING (VC++ 6. catch. Lecturer in Computer Science. If not. CATCH. The program execution is interrupted. MFC provided macros to deal with exceptions.0) EXCEPTION HANDLING MFC Error and Exception Handling The exception-handling mechanisms available in MFC are two C++ exceptions (available only in MFC 3. use C++ exceptions along with the macros.0 and later) MFC exception macros should be used only if they already reside in existing code. MFC Exception Macros MFC versions lower than 3. THROW_LAST This macro throws a locally created exception. which signifies the block of code where the throwing of exceptions occurs. THROW_LAST passes the exception correct to the next CATCH handler. and THROW..0 or later) MFC exception macros (available in MFC 1. The macro sends the exception back to the next CATCH block. The exceptions are processed in the CATCH and AND_CATCH blocks. In contrast.124 - . it goes out of scope. The macros are TRY. KCCS Warangal . The TRY block is ended with an END_CATCH or END_CATCH_ALL macro. thus being deleted.

AND_CATCH_ALL This macro catches additional exception types thrown by a preceding TRY block. and then use AND_CATCH for every other exception type. Thirupathi MCA. END_CATCH_ALL Signifies the end of the last CATCH_ALL or AND_CATCH_ALL block. Here are some possible program skeletons using these macros: TRY { } CATCH() { } AND_CATCH() { } END_CATCH and TRY { } CATCH_ALL() { } THROW_LAST(). The TRY block should end with END_CATCH_ALL. KCCS Warangal . END_CATCH This macro signifies the end of the last CATCH or AND_CATCH block. Lecturer in Computer Science.. Use the CATCH macro to catch the first exception type.WEB AND VISUAL PROGRAMMING (VC++ 6.125 - . The TRY block should end with END_CATCH. and then use AND_CATCH_ALL for all other exception types. AND_CATCH You use this macro to catch additional exceptional types thrown from a preceding TRY block.0) CATCH This macro defines a block of code that catches the first exception thrown by a preceding TRY block. By R. Use the CATCH macro to catch the first exception type. The TRY block should end with END_CATCH.

KCCS Warangal . Thirupathi MCA. Each of these exceptions is derived from the base class CException. CInternetException—An exception condition coming from the Internet classes. which uses CFileException: //Try Block try { By R. COleDispatchException—Handles exceptions specific to the OLE IDispatch interface. CDBException—An exception condition coming from the database classes.0) Predefined Exceptions for MFC Here is a list of predefined exceptions to use the MFC. take a look at the following code fragment. The memory allocation functions C++ uses will trigger this exception.. You can use these with C++ exceptions directly or with the MFC exception macros. CMemoryException—A memory exception that signifies an out-of-memory condition. CArchiveException—A serialization exception condition. These objects are constructed and thrown in CFile member functions and in member functions of derived classes. COleException—An exception condition from an OLE operation. Lecturer in Computer Science. Memory exceptions are thrown new. Recovering from such an error is difficult and unlikely.WEB AND VISUAL PROGRAMMING (VC++ 6. CResourceException—Generated allocated. This exception can be triggered by calling this function: AfxThrowMemoryException() The CFileException For a quick introduction. CNotSupportedException—An exception that results from a request of a feature not supported. using the throw/catch exception mechanism.126 - . These are constructed and thrown from inside CArchive member functions. when a resource cannot be found or CUserException—Thrown to stop an end-user operation in the same manner as covered in the earlier section on C++ exception handling. CFileException—A file-related exception condition. CDAOException—An exception condition from the MFC database classes based on data access objects (DAOs). The CMemoryException The CMemoryException exception is raised when the program simply can no longer allocate any more memory.

It is important to delete the exception class objects when you are finished with them. the catch block will catch the thrown exception and create the exception class object e. Thirupathi MCA. cause. is a cause code for the exception (listed earlier). It gets placed in the m_strFileName By R.WEB AND VISUAL PROGRAMMING (VC++ 6. Unlike C++ exception handling. The function can take three parameters: The first one is required. It is this code that is placed in the m_cause member in the catch group. a message appears telling the user that The File has not been opened. is used to specify an operating system error code. The third parameter is strFileName. e->Delete().127 - . There are a few cause codes besides CFileException: • • • • • • • • • • • • • • • CFileException::accessDenied CFileException::badpath CFileException::badseek CFileException::directoryFull CFileException::diskFull CFileException::endOfFile CFileException::fileNotFound CFileException::generic CFileException::hardIO CFileException::invalidFile CFileException::lockViolation CFileException::none CFileException::removeCurrentDir CFileException::sharingViolation CFileException::tooManyOpenFiles You can trigger this exception by calling the AfxThrowFileException() function.. } catch(CFileException* e) //Catch the file exceptions { if (e->m_cause == CFileException::fileNotFound) AfxMessageBox("The File has not been opened. If this exception is equal to fileNotFound. When a CException is raised. } The try block guards the code to perform file operations. The first parameter.0) CFile fileNotOpen fileNotOpen. The final statement deletes the exception class object. lOsError. Lecturer in Computer Science. this is not taken care of automatically. and the other two are optional. The second parameter.SeekToBegin(). KCCS Warangal .").

The class includes a public data member that contains the cause of the exception. Lecturer in Computer Science.128 - . The m_cause member of the CArchiveException class holds the archive-specific cause codes. The errors it returns are always specific to the DAO itself. You can trigger this exception by calling the AfxThrowNotSupportedException() function. You can throw this exception by calling the AfxThrowDaoexception() function. The nAfxDaoError is a DAO error code specific to DAO. KCCS Warangal . This function has two optional parameters: nAfxDaoError and an OLE scode value. The CResourceCollection The CResourceCollection exception is raised when the application can't allocate or find the requested system resources. The nAfxDaoError codes can be any from the following list: • • AFX_DAO_ERROR_DFX_BIND AFX_DAO_ERROR_ENGINE_INITIALIZATION By R. Thirupathi MCA. This exception can be triggered by calling the AfxThrowResourceException() function. The OLE scode value comes from a DAO-based OLE call. The CArchiveException The CArchiveException object represents a serialization exception condition.WEB AND VISUAL PROGRAMMING (VC++ 6. The CDaoException The CDaoException is used for DAO-based database access. as listed here: • • • • • • • • CArchiveException::badClass CArchiveException::badIndex CArchiveException::badSchema CArchiveException::endOfFile CArchiveException::generic CArchiveException::none CArchiveException::readOnly CArchiveException::writeOnly The NotSupportedException The CNotSupportedException object is generated when a request is made for an unsupported feature..0) member string variable and holds the filename of the file that was being accessed when the error occurred.

The second form has three parameters as well. The last parameter is a help context ID. Lecturer in Computer Science. KCCS Warangal . By R. There are two forms to this function.0) • • AFX_DAO_ERROR_OBJECT_NOT_OPEN NO_AFX_DAO_ERROR COleException and COleDispatchException There are two OLE exception errors: COleException and COleDispatchException. The most common use of the ASSERT macro is to locate program errors during development. The ASSERT Macro You use the ASSERT macro to check assumptions made by the functions in the program. The COleException error normally is used for server-side or OLE-specific operations. The ASSERT macro catches errors only when using the debug version of MFC. This example shows how you can use the ASSERT clause: int FunctionResult = AnyFunction(x). The second parameter is nDescriptionID for a UINT resource code.. The first parameter is a wCodeWORD value that is an application-specific error code. the last one optional. Nothing happens if the argument is true (not zero). The second parameter is an lpszDescription string pointer to represent the verbal string for describing the error. the program is halted and the developer is alerted.WEB AND VISUAL PROGRAMMING (VC++ 6. You can trigger this exception by calling the AfxThrowOleException() function. Thirupathi MCA. passing an OLE scode value.129 - . This value then is stored in the m_sc member of the exception. The COleDispatchException class is used in conjunction with OLE IDISPATCH interfaces and is thrown by the AfxThrowOleDispatchException() function. ASSERT (FunctionResult < 0). You can trigger this exception by calling the AfxThrowNotSupportedException() function. The first parameter is a wCodeWORD value that is an application-specific error code. The last parameter is a help context ID. Both forms are nearly identical—the difference is the second parameter. If the argument expression is false (0). which represents a verbal string describing the error. It automatically is turned off and produces no code when the program is rebuilt with the release version of MFC. The first form has three parameters—the first two required. The CUserException You use the CUserException class to generate exception objects for applicationspecific applications.

Regedit Root Keys Key HKEY_CLASSES_ROOT Description Symbolic link to HKEY_LOCAL_MACHINE \SOFTWARE \Classes. The macro validates the pointer of the object. This key contains other keys that are hives. Choosing Ignore continues the program. Hives On disk. but such is not the case. starting point) of the tree. HKEY_CURRENT_USER Symbolic link to a key under HKEY_USERS representing a user's profile hive. and calls the object's own AssertValid member functions. HKEY_LOCAL_MACHINE Placeholder with no corresponding physical hive. The correlation between the keys that regedit displays and the content of the hives isn't straightforward.e.130 - . Choosing Abort terminates program execution. a message box appears with the following text: assertion failed in file <name> in line <num> Abort Retry Ignore where <name> is the name of the source file and <num> is the line number of the assertion that failed. checks it against NULL. Thirupathi MCA.. Neither Abort nor Ignore activates a debugger.0) If the argument is false. Lecturer in Computer Science. The ASSERT_VALID Macro You use the ASSERT_VALID macro to test the validity of an object's internal state. KCCS Warangal . An alert message is displayed similar to ASSERT if any of the tests fail. the Registry isn't simply one large file but a set of discrete files called hives.. You might think that NT stores each root key you see when you run one of the Registry editors (regedit or regedt32) in a separate hive. Each hive contains a Registry tree. Choosing Retry breaks into the debugger. Subkeys and their values reside beneath the root.WEB AND VISUAL PROGRAMMING (VC++ 6. By R. ASSERT_VALID calls the AssertValid member function of the object passed as its argument. which has a key that serves as the root (i.

0) Key HKEY_USERS Description Placeholder that contains the userprofile hives of logged-on accounts.WEB AND VISUAL PROGRAMMING (VC++ 6. Lecturer in Computer Science. HKEY_DYN_DATA Placeholder for performance data lookups.131 - . This key has no corresponding physical hive. HKEY_CURRENT_CONFIG Symbolic link to the key of the current hardware profile under HKEY_LOCAL_MACHINE \SYSTEM CurrentControlSet\ Control\IDConfigDB\Hardware Profiles. KCCS Warangal .. Thirupathi MCA. By R.

Sign up to vote on this title
UsefulNot useful

Master Your Semester with Scribd & The New York Times

Special offer for students: Only $4.99/month.

Master Your Semester with a Special Offer from Scribd & The New York Times

Cancel anytime.