Mozilla Developer News reports that Firefox 3 will be officially launched next Tuesday, June 17. Make sure you download your copy that day, to help Mozilla break the world download record. I've been using Firefox 3 for a while now, and it's worlds better than Firefox 2 (which was already super awesome).
Firefox 3 Next Tuesday!
Jun 12, 2008Displaying Recent Comments
Jun 5, 2008I have added a new section to the sidebar of this site, showing the most recent comments posted here. Hopefully, this will help foster further discussion on older topics (which occasionally get comments). This new feature comes via the aptly named Recent Comments WordPress plug-in. I'm quite impressed with the customization options available, and installation was a snap.
Does anyone have any recommendations for how the recent comments list should appear? Plenty of options are available, including an excerpt preview of each comment. I tried several options out, but I'm not sure what visitors would find most useful.
Your suggestions would be appreciated.
Who Doesn’t Use Anti-Virus?
May 31, 2008Are there any readers here who use Windows and don't make use of an anti-virus client? I've been thinking about ditching my anti-virus client altogether on my personal system, and after reading an interesting article on the subject, I'm wondering if anyone else out there has taken this route. In my experience, anti-virus solutions are slow, ineffective (I'm not sure they've ever flagged anything for me over the years), and are generally a bother to keep up with.
If you've ditched anti-virus, why'd you do it? And what have been your results?
Officially Switching to Firefox 3
May 23, 2008It's official: I am switching to Firefox 3 RC1 as my primary web browser. All of the extensions I use are now compatible in some form or another (Firebug and Linkification are still in 'beta'), so that's no longer holding me back.
One interesting note about Firebug. The new version has removed the 'Disable / Enable' feature for individual sites. Or so I thought. This functionality has now been moved to the Network Monitor and Script Debugger sections of the extension. In other words, I can now explore the DOM tree for any site, without having to pay the performance hit from the network monitoring code. Woo-hoo!
Exiting Batch File Contexts
May 22, 2008While working on a Windows batch script earlier today, I ran across an interesting side effect of the call
and exit
commands. Let's take this simple example, which we'll name script_a.bat:
@echo off
SETLOCAL
call :function
cd %SOME_PATH%
goto :functionEnd
:function
set foobar=1
if "%foobar%" == "1" exit /B 1
goto :EOF
:functionEnd
Unlike Bash, Windows batch files have no function capabilities. Clever hacks like the above can be used to fake out functions, but these hacks hide some subtle quirks. You see that exit
call within the 'function'? It only gets called if the %foobar%
variable is equal to 1 (which is always the case, in our example). Also note that we exit with an error code of 1. So, in short, this script should always return an exit code of 1. Now, let's create another batch script which we'll name script_b.bat:
@echo off
call script_a.bat
echo Exit Code = %ERRORLEVEL%
This second script is very simple. All we do is call script_a.bat, and then print its resulting return code. What do you expect the return code to be? One would expect it to be 1, but it's not! Our second script will actually print out Exit Code = 0
. Why is this?
The answer lies in the call
command. Again, unlike Bash scripts, stand-alone batch files do not create their own context when executed. But if you use the call
command, the thing you call does get its own context. How weird is that? So, let's trace the first script we wrote to figure out where the error code gets changed.
After some initial setup, we call our function (call :function
). Inside our function, we create a variable, initialize it to 1, then test to see if the value is 1. Since the value is indeed 1, the if
test succeeds, and the exit
command is called. But we don't exit the script; instead, we exit the context that was created when we called our function. Note that immediately after we call our function, we perform a cd
operation. This line of code gets executed, succeeds, and sets the %ERRORLEVEL%
global to 0.
In order to exit properly, we have to exit our initial script twice, like this:
@echo off
SETLOCAL
call :function
if "%ERRORLEVEL%" == "1" exit /B 1
cd %SOME_PATH%
goto :functionEnd
:function
set foobar=1
if "%foobar%" == "1" exit /B 1
goto :EOF
:functionEnd
See the new exit
call after our initial function call? Then, and only then, will our second script print out what we expected. This subtle behavior stymied me for several hours today; hopefully this short post will help someone else avoid this frustration.
Interesting Office Finale
May 17, 2008The season finale for The Office was aired last night, and it really threw me for a loop. A lot of what I expected to happen didn't, and some surprising twists and turns occurred throughout the entire episode. Some of my predictions are coming to fruition, though others may be increasingly off the mark. Like before, there are spoilers ahead so be forewarned.
- Jim and Pam
- I'm surprised that the Jim-Pam storyline took a turn at the end, with Jim failing to propose to Pam (as I expected would happen). Hopefully we'll see the couple take this step at the beginning of next season. I'm not sure I can take the tension any longer!
- Jim taking career risks
- Jim's two voice-mails to Ryan don't bode well for the future of his career. If Ryan is able to dodge his current criminal problems, Jim could be in trouble.
- Ryan gets his comeuppance
- This prediction came true, though not in the way I expected. It seemed to me that Ryan's drug problem would catch up to him, but it turns out that his business fraud was what got him into trouble with the law.
- Michael grows up
- For the first three-quarters of this episode, Michael was maturing at an incredible pace. His behavior around Holly, the new HR rep, was remarkable. Unfortunately, he relapses after finding out Jan is pregnant. I truly hope he ditches Jan and doesn't fall back into his old ways.
- Angela, Andy, and Dwight
- I certainly didn't see the Angela-Andy proposal coming. And what's up with Angela and Dwight at the very end of the episode? Who knew that they have apparently been seeing one another? This storyline should be very interesting to follow.
- Holly and Kevin
- I absolutely loved the running joke where Holly thought that Kevin was slow-minded. The entire gag was genuinely funny, and Brian Baumgartner did an amazing job as Kevin (this is his best performance so far in this show).
What did you think of the finale? Are you as excited about next year's season as I am?
Kensington Digital FM Transmitter Review
May 12, 2008
Back in November, I picked up a Kensington Digital FM Transmitter for my iPod Classic. And on my way back from Dustin and Sarah's wedding yesterday (congratulations, you guys!), it occurred to me that I hadn't yet posted a review of the device.
Having never used an FM transmitter before, I was unsure about the reception quality. Thankfully, this specific Kensington model is top notch. It's rare that I encounter static, and I've noted that it most often happens when driving under a particularly large overpass. The audio quality is excellent, though I find that I have to turn up the volume on my car stereo a little higher than I normally would with the corresponding audio CD. This might simply be related to the compression that MP3's provide, but it's a minor nuisance.
The unit provides 3 preset buttons, which is very useful to lock in multiple unused stations. This feature was really handy when I went to the mountains last Thanksgiving; one of the preset stations I was using in the RTP area was being used in the Asheville area, and switching was simply a matter of pressing a button (and then tuning to the right place on the receiver).
While your iPod is attached, the unit charges the battery. Unfortunately, there's no option to not charge the battery, which would be useful for battery conditioning purposes. I don't use this unit every day, so this minor problem doesn't impact me as much. One other minor annoyance is that the iPod-style connector doesn't lock into place. This makes it much easier for the cable to fall out, though I have only seen this happen a time or two.
Overall, I really like this unit. According to the Amazon product page, this particular model is being phased out and replaced by the Kensington LiquidFM Transmitter, which has much lower reviews. If you want one of these models, I suggest picking it up ASAP. You will not be disappointed.
Crysis Mini-Review
May 11, 2008I completed Crysis yesterday, so I thought I would post a few quick thoughts on my experience:
What I Liked
- As can be expected, the graphics in this game are insane. The jungle atmosphere is spot-on, physics are incredible, lighting is superb, and character modeling is excellent. Visually, this game is a real treat to play.
- The nano-suit which the player wears is an interesting game play mechanic. 'Health' is handled via the nano-suit, and the abilities which the suit provides (speed, strength, armor, and cloak) are fun to play with.
- Level design is excellent. All of the locations feel incredibly realistic, and there's a ton to explore. I'll probably play through the game once more just to fully explore each map, because I know there's a ton of stuff I missed.
What I Didn't Like
- Crysis isn't near as long as Far Cry, which really disappointed me. Likewise, the maps in Crysis aren't as large either.
- Crysis has an incredibly weak story line, much like Far Cry did. This comes as no surprise, especially in the FPS genre, but I was hoping for a little more meat than what I was given.
- Again, just like Far Cry, the game turns into a battle against alien forces. I really enjoyed battling the human forces in the early parts of this game, and I wish Crytek had stuck to that theme. The later alien-based levels are, for the most part, not very fun. Why can't we get a game that uses this style engine and doesn't devolve into a 'save-the-world-from-alien-attack' kind of story? Perhaps Far Cry 2 will provide the kind of experience I'm looking for.
- Difficulty is really uneven. I played through on the 'Normal' difficulty, and found myself stuck at a few places (though I never got stuck permanently). Some battles are surprisingly easy, while others are incredibly hard to survive.
- Some of the vehicles the player gets to drive are woefully difficult to maneuver, which is frustrating. I'm not entirely sure why this is, because the vehicles in Far Cry were a pleasure to drive.
- This game is a system hog. I played at 1280x1024 on the High setting (no anti-aliasing or anything fancy), and there were still a few moments where things really chugged (entering and exiting buildings especially). Overall my experience was smooth, but these moments of stuttering killed some of the immersion factor.
I'm not sure if I can recommend this game or not. It's worth playing through for the eye candy, but some of the game's frustrations cancel out that fun. My final verdict for Crysis? C+
Page Redirection Fixed
May 9, 2008A recent Lifehacker article on the Top 10 Tools to Get Blogging Done featured my oh-so-handy CoLT extension. Unfortunately the article linked to the old URL, for which I failed to provide a redirect. This problem is now fixed, and the broken URL now redirects to the new location.
You've got to tell me about this kind of stuff people!
Doing Credits Right
May 6, 2008I just finished Half-Life 2: Episode Two again. Playing it through on my new computer was a real treat, and the ending of this episode still brings a tear to my eye. One thing jumped out at me for the first time on this play-through: the end credits. Valve has chosen to present the end credits in a short, yet elegant way. Every contributor is listed in alphabetical order by last name, with only a few notable exceptions (all the voice talent is singled out, for example). The result is a short, concise credits sequence that isn't a bore to sit through. Compare this with the end credits for Call of Duty 4, which go on for so long that a rap song is performed to break the monotony (I believe the end credits are on the order of 3 or 4 minutes long in that particular title).
I'd really like to see more end credit sequences patterned after Valve's design. Others may disagree, but knowing who did what on a project isn't very important. Listing each contributor in a single group levels the playing field and gives everyone an equal measure of thanks.
Predictions for The Office
May 2, 2008I'm a big fan of The Office, the comedy television show on NBC (hopefully everyone else is too). Last night's episode was great, and it provided a glimpse of what might be coming down the pipeline (there are only 2 episodes left this season). Here are a few predictions I have for where this series is headed; note the possible spoilers ahead:
- Jim proposes to Pam
- This seems pretty obvious, and I wouldn't be surprised if it happens during the last episode of this season (and on top of the Dunder-Mifflin building). The proposal will most likely occur either during or immediately after the events of my next prediction...
- Jim to be fired (or transferred)
- Ryan had some harsh words of warning for Jim last night, thanks to a spiteful Toby (who's scheduled to depart in the coming weeks). I predict that Jim will indeed either (a) be let go from the company, or (b) be transferred away from the Scranton branch, due to his 'wasting time' at work. The latter option in my opinion is most likely, and I predict that he gets transferred to the Dunder-Mifflin branch in Utica, which is now managed by his previous girlfriend Karen. Awkward situations are bound to follow, especially if Pam comes along for the ride (as Jim's fiancée).
- Ryan gets his comeuppance
- It's pretty obvious that Ryan is a jerk, and we've now learned that he has a drug problem. I predict that this will catch up to him, and he will fall from his current heights, providing him with some much needed payback.
- Roy to return?
- If we assume that Jim leaves the Scranton office, and Pam doesn't come along, his relationship with her will be subsequently strained. I predict that Roy will make another appearance (perhaps hired by Vance refrigeration?), and will cast some doubt in Pam's mind as to who she should be with.
- Michael grows up
- For the first time ever, we are seeing some growth in Michael. He finally stood up to Jan, and he showed much more maturity with Stanley in last night's episode. I think Michael will continue to mature, and the show will slowly stop revolving around his character (it's time to flesh out some of the other characters in the show).
NBC has ordered an entire season of The Office for next year, so I'm excited to see where things are headed. What are your predictions?
Gold Rush: First Impressions
May 1, 2008The long-awaited update to Team Fortress 2 was released Tuesday evening, so I've only had a brief amount of time to play around with Gold Rush, the map showcasing the new payload game type. In a word, the new game play theme is awesome. Gold Rush is much more enjoyable than Dustbowl (which I love, by the way), and I really hope more maps of this type are released over time.
Here's how Gold Rush works. A mine cart, carrying a Fat Man style bomb, must be moved from point A to point B through 3 different stages. The attacking team (BLU) moves the cart simply by standing near it; the more team members surround the cart, the faster it moves. If the cart is left unattended for 30 seconds, it begins to move backwards towards the starting point. The map is played just like Dustbowl; there are a total of 3 stages in which BLU attacks and RED defends. Once either BLU successfully attacks all stages, or RED successfully defends a stage, the teams swap sides and the stages are played again.
Gold Rush is definitely a tough map. The defending team almost always has a height advantage, making it difficult to make quick progress. A number of choke points slow things down even more. But like every other map in Team Fortress 2, things are very well balanced.
The other major change to the game comes through the new unlockable weapons and achievements. Medic is the only player class that currently supports these new features, so everyone is inevitably playing as a Medic. A total of 36 new achievements are available, and for every 12 that you unlock, a new weapon option becomes available. First up is "The Blutsauger," a syringe gun mod that leeches health from each enemy you hit. Next is "The Kritzkrieg," a medi-gun mod that gives the person you use it on a 100% chance of firing critical damage (instead of the standard Ubercharge). Finally, "The Ubersaw" bone-saw mod provides a 25% charge to your Ubercharge meter for every hit you make on an enemy. I've only gotten 4 out of the 36 achievements so far (Surgical Prep, Trauma Queen, Intern, and Group Health), so I've got quite a ways to go. Some of the achievements look impossible to get, so I doubt I'll make it all the way.
If you'd like to try out Team Fortress 2, along with the new updates, Valve is offering a free weekend this weekend (May 5-6). I can't recommend this game highly enough, and the Steam service is great, so check it out. If you do check it out, look for me; my username is jgbCodeMonkey.
Jonah’s Rig 3.0
Apr 29, 2008Last week, I rebuilt my computer again (making this the third machine I've run on since this site opened up). Here's the list of what I upgraded in the system:
- ABit IP35 Pro Motherboard
- A great motherboard with passive coolers on the MCH, ICH, and PWM component areas. A very handy digital readout is available on the board to troubleshoot boot-up issues (no more beep codes), and the overall layout is excellent. However, I have a few minor problems with the board. The SATA connectors are angled at 90 degrees, making it very difficult to attach the cables from my drives. I'm currently using SATA ports 5 and 6, because ports 1 through 4 are physically inaccessible. Also, my wireless network card wasn't happy with the board, and I had to switch back to my old one, which has lousy reception. I'm going to fix this problem in a novel way; stay tuned for further details.
- Intel Core 2 Duo E8400 Wolfdale CPU @ 3.0 GHz
- After much thought, I decided to go back to an Intel CPU (after using an AMD X2 4400+ for a while). The Intel chips are just faster right now, and they use less power, allowing them to run a little cooler. I had a difficult time getting the stock heat sink to snap into the mounting holes on the motherboard, causing the motherboard to bend around the CPU socket (which concerns me). I'll probably spring for an after-market cooler at some point to remedy this situation.
- 2 GB of Geil DDR2 800 (PC2 6400) SDRAM
- I've never used the Geil brand of memory before, but Anandtech recommended it on their last holiday buying guide, so I picked some up. The chips run at a default 5-5-5-15 timing, but they support 4-4-4-12. I made one attempt at overclocking the chips, but Windows wouldn't boot, so I reverted back to the defaults. Changes in the default memory voltage is probably warranted here, which is something I failed to do on my first try. The copper-orange heat spreaders are very sexy.
- BFG Tech GeForce 8800 GTS (G92) 512 MB
- The 8800 GTS-512 line of graphics cards is based on the new nVidia G92 chipset (using a 65nm die). It's notably faster than the 8800 GT, which is the card I had my eye on for a long time. The 8800 GTS has a larger cooler that's not as loud, and it's a beast of a graphics card. This is the first card I've had that takes up two slots on the motherboard, leaving me with only 2 out of the 3 available PCI slots. It runs a little warm (70 degrees Celsius at load), but I'm willing to live with that for now.
- Corsair CMPSU-620HX 620W Power Supply
- I was concerned that my old 500 W power supply wouldn't have the juice required for this new build, so I bought this highly recommended Corsair model. It's modular, which allows me to use as few cables as I need, and it's incredibly quiet.
- 2 Seagate Barracuda SATA 250 GB Hard Drives
- These Seagate drives are a little faster than my old ones, they're 90 GB larger, and they have double the cache (16 MB).
I have been test driving this new setup with a few games. Call of Duty 4 looks amazing in high resolution with all the eye candy turned on, and it has elevated my opinion of the game. The Crysis demo ran great at 1280 x 1024 at the 'High' graphics setting, and I may be able to push it a little farther (I've ordered the full game, by the way; I'm very excited). Team Fortress 2 is thrilling at 1600 x 1200, and even Half-Life 2, which will be four years old later this year, looks great running at 1600 x 1200 with 4x FSAA. Half-Life 2: Episode 2 should be equally as nice.
SSL URI Identification in Firefox 3
Apr 28, 2008The last few Firefox 3 nightly builds have changed the way SSL URI's are displayed to the user. In Firefox 2, accessing a secure site results in a yellow background for the address bar (which I think is a particularly elegant solution). For reasons I don't fully understand, Mozilla is getting rid of this implementation. In new Firefox 3 builds, the background of the 'favicon' will change depending on the security of the site. A blue background indicates an SSL secured site, while a green background indicates an EV SSL secured site. Moving the color to the favicon, in my opinion, makes things a little harder to understand. A heated debate about this inevitably appeared in the corresponding bug, and there will likely be more confusion over this in the future, as more public users begin to explore the Firefox 3 world. I fully expect an extension to 'fix' this feature, so all may not be lost. This is a very strange decision on Mozilla's part, and it should be interesting to see what the end result is.
An Official WordPress Contributor
Apr 17, 2008I am now an official WordPress contributor! While converting Born Geek to WordPress, I noted that the Movable Type importer did not obey the WordPress database case constraints. Movable Type posts export themselves as "Published" while WordPress expects the value to be lower case ("published"). After finding and verifying this bug, I wrote it up and submitted a simple patch, which was then accepted. The fix will be included in 2.5.1!
Team Fortress 2 Update Preview
Apr 16, 2008There's a great article over at ShackNews offering a preview of the new Team Fortress 2 updates coming in the next week or two. In addition to discussing the new Goldrush game type, they also take a look at the brand new unlockable weapons for the Medic class. Some of the new weapons really sound exciting, and I'm really looking forward to this update.
Site Conversion Completed
Apr 12, 2008I have (mostly) completed the conversion of this site from Movable Type to WordPress 2.5. As always, there will be plenty of tweaking over the next few days. If you find anything out of the ordinary, please leave a comment on this post, or contact me directly. I've done my best to prevent broken links on the site, but there's always a chance I missed something.
Moving Born Geek to WordPress offers several benefits:
- Articles and posts are easier to update.
- Static content and news postings no longer need to be separated into multiple "blogs."
- Comment spam is much easier to manage (and prevent).
- The administration interface is much nicer.
I have yet to turn on any WordPress caching, so please excuse any slow performance for the next few days. The WP-Cache plugin apparently has a few issues with WordPress 2.5, and I haven't yet investigated the alternate WP Super Cache plugin.
Copying Text to the Clipboard
Apr 12, 2008Sending the contents of a CString
object to the clipboard is a quick and easy task when the following function is used:
BOOL SendTextToClipboard(CString source)
{
// Return value is TRUE if the text was sent
// Return value is FALSE if something went wrong
if(OpenClipboard())
{
HGLOBAL clipbuffer;
char* buffer;
EmptyClipboard(); // Empty whatever's already there
clipbuffer = GlobalAlloc(GMEM_DDESHARE, source.GetLength()+1);
buffer = (char*)GlobalLock(clipbuffer);
strcpy(buffer, LPCSTR(source));
GlobalUnlock(clipbuffer);
SetClipboardData(CF_TEXT, clipbuffer); // Send the data
CloseClipboard(); // VERY IMPORTANT
return TRUE;
}
return FALSE;
}
So what's going on here? We first test to see if we can successfully open the clipboard from our program. Note that once we have called the OpenClipboard()
function, no other program can modify the clipboard contents. Because of this, it is very important that later on in our code we call the CloseClipboard()
function. This way, others can access the clipboard as needed.
We create a local handle to a global memory block as well as a local character buffer. A call to the EmptyClipboard()
function clears out anything that might already be on the clipboard. Following that, we allocate a specified number of bytes in the global memory heap. This is where the string will be stored for future use. We then lock the global memory block (so we don't lose our storage), assigning the memory pointer as necessary. Then we copy the text from the CString
into the character buffer, unlock the global memory storage chunk and send the data to the clipboard.
Finally, we call the CloseClipboard()
function! The code then ends by returning true (since we successfully copied the text).
Control Specific Context Menus
Apr 12, 2008Context menus (or "right-click popup" menus) come in two flavors: application-wide or control-specific. This article focuses on the latter. If you are interested in application-wide menus, be sure to check out my article on that very subject.
Adding the Menu Resource
The first step in creating a context menu is simple: use the Visual Studio resource editor to create the menu you wish to display. Make sure that you give it a unique ID; I will use the value IDR_POPUP_MENU
for this example. Add to the menu the various menu items that you want to include. Note that your context menu should only have one top-level item (under which all other menu items will be placed). The caption for this top-level item can be whatever you like since the user will never see it. If you are mapping menu items in this context menu to commands that already exist in the program (as is likely), make sure that you give each menu item the appropriate ID. For example, if the ID to my "Open File" command in my main application menu is ID_FILE_OPEN
, I would give that same ID to the corresponding item in my context menu. If you aren't mapping commands, simply add any message handlers as normal.
Displaying the Menu
After you create the menu resource, we need to write the code that's responsible for showing the menu when the user right-clicks a specific control. For this example, I will assume that the control we are adding a menu to is a CListCtrl
. Add the NM_RCLICK
event handler to your list control, and edit the resulting handler method to look like the following:
void CYourDlg::OnRclickYourList(NMHDR* pNMHDR, LRESULT* pResult)
{
CPoint point;
GetCursorPos(&point);
CMenu mnuTop;
mnuTop.LoadMenu(IDR_POPUP_MENU);
CMenu* pPopup = mnuTop.GetSubMenu(0);
ASSERT_VALID(pPopup);
pPopup->TrackPopupMenu(TPM_LEFTBUTTON | TPM_RIGHTBUTTON |
TPM_LEFTALIGN, point.x, point.y, AfxGetMainWnd(), NULL);
*pResult = 0;
}
Understanding the Code
Let's examine this code so that we know exactly what's going on. We first create a CPoint
object so that we can store the location of the mouse when the user clicks the right mouse button. Since the message is only fired when the user clicks within the list control, we can simply use a call to the GetCursorPos()
method to get the mouse's current screen coordinates. We then create a menu object and attach the menu resource we created earlier to it. The parameter to the LoadMenu()
method is simply the unique ID that we assigned to our menu.
Next, we set up a pointer to a menu object (this is what will actually control the popup menu). The pointer gets assigned to the return value of the GetSubMenu()
method. The parameter that is passed here is the zero-based index of the submenu that will be used as the popup menu. Since our menu resource has only one top-level item, we need only to pass a parameter value of zero.
We finally use the TrackPopupMenu()
method to create and draw the menu itself. The first parameter sets a screen position flag and a mouse button flag. As you can see from the flags I pass in, I allow the user to select menu items with either the left or right mouse buttons (which are the only two choices), and I align the left of the menu with the coordinate specified by the x parameter.
The next parameter is indeed that x value, which specifies the horizontal screen coordinate where the popup menu should appear. Likewise, they y (vertical) parameter follows the x value. In both cases, we use the CPoint
object's values that we got from our call to GetCursorPos()
.
The fourth parameter identifies the window that owns this popup menu. This window will receive all the messages sent from the menu, so we pass AfxGetMainWnd()
in order to get the application's main window object.
The final parameter is either a RECT
structure or CRect
object that specifies a rectangular area in which the user can click without dismissing the popup menu. If you just leave this set to NULL, things will work properly (i.e., clicking outside of the menu will dismiss it).
Application Context Menus
Apr 12, 2008Context menus (or "right-click popup" menus) come in two flavors: application-wide or control-specific. This article focuses on the former. If you are interested in control-specific menus, be sure to check out my article on that very subject.
Implementing the Application Popup Menu
The first step in creating a context menu is simple: use the Visual Studio resource editor to create the menu you wish to display. Make sure that you give it a unique ID; I will use the value IDR_POPUP_MENU
for this example. Add to the menu the various menu items that you want to include. Note that your context menu should only have one top-level item (under which all other menu items will be placed). The caption for this top-level item can be whatever you like since the user will never see it. If you are mapping menu items in this context menu to commands that already exist in the program (as is likely), make sure that you give each menu item the appropriate ID. For example, if the ID to my "Open File" command in my main application menu is ID_FILE_OPEN
, I would give that same ID to the corresponding item in my context menu. If you aren't mapping commands, simply add any message handlers as normal.
In order to display the context menu to the user when they click the right mouse button, we need to add a handler for the WM_CONTEXTMENU
message. This handler should be added to the window class that will handle the menu's message calls. Most often, this class will be your view class, but note that any CWnd
based class will do.
Once the message handler has been added, insert the following code into the WM_CONTEXTMENU
handler's method:
// We might need to adjust the origination point for the
// keyboard context menu
if(point.x == -1 && point.y == -1)
{
CRect rect;
GetClientRect(&rect);
point = rect.TopLeft();
point.Offset(5,5);
ClientToScreen(&point);
}
// Load the top level menu from the resource we created
CMenu myMenu;
myMenu.LoadMenu(IDR_POPUP_MENU);
// Now extract the (one and only) popup menu item from
// this menu resource
CMenu* myPopup = myMenu.GetSubMenu(0);
// Let's display the menu!
myPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,
point.x, point.y, AfxGetMainWnd(), NULL);
Understanding the Code
The first thing we do is to handle the case where the user invokes our context menu via the keyboard. In this scenario, we adjust the origination point for the menu. Next, we load the menu resource that we created earlier and extract the popup menu item (the one and only top-level item). The popup menu extraction is performed by using the GetSubMenu()
method, and passing the (zero-based) index of the item to extract. Since we only had one top-level menu item, a value of zero gets passed in.
Finally, we make a call to the TrackPopupMenu()
method to display the menu to the user. The first parameter in this method call is a series of flags used to specify where the menu shows up in relation to the mouse cursor, as well as what buttons can be used to select the menu items. The screen position may only be one of the following:
TPM_CENTERALIGN
- Centers the menu horizontally relative to the coordinate specified by x.TPM_LEFTALIGN
- Positions the menu so that its left side is aligned with the coordinate specified by x.TPM_RIGHTALIGN
- Positions the menu so that its right side is aligned with the coordinate specified by x.
The mouse button flag can be any combination of the following two values:
TPM_LEFTBUTTON
- Causes the menu to track the left mouse button.TPM_RIGHTBUTTON
- Causes the menu to track the right mouse button.
The next two parameters in the TrackPopupMenu()
call specify the horizontal and vertical locations of the menu (the horizontal position depending on the flag used in the first parameter). Next comes a pointer to the window that owns the popup menu. Since we want our messages to be routed to our top-most parent, we use a call to AfxGetMainWnd()
to get the top level window. The final parameter defines a CRect
in which the user can click without dismissing the popup menu. A value of NULL here will do the right thing: clicking outside of the menu will dismiss it.