-
This article is from "The Old New Thing", a great place for windows developers.
Setting focus in a dialog box is more than just calling SetFocus.
A dialog box maintains the concept of a "default button" (which is always a pushbutton). The default button is typically drawn with a distinctive look (a heavy outline or a different color) and indicates what action the dialog box will take when you hit Enter. Note that this is not the same as the control that has the focus.
For example, open the Run dialog from the Start menu. Observe that the OK button is the default button; it has a different look from the other buttons. But focus is on the edit control. Your typing goes to the edit control, until you hit Enter; the Enter activates the default button, which is OK.
As you tab through the dialog, observe what happens to the default button. When the dialog box moves focus to a pushbutton, that pushbutton becomes the new default button. But when the dialog box moves focus to something that isn't a pushbutton at all, the OK button resumes its position as the default button.
The dialog manager remebers which control was the default button when the dialog was initially created, and when it moves focus to something that isn't a button, it restores that original button as the default button.
You can ask a dialog box what the default button is by sending it the DM_GETDEFID message; similarly, you can change it with the DM_SETDEFID message.
(Notice that the return value of the DM_GETDEFID message packs the control ID in the low word and flags in the high word. Another place where expanding dialog control IDs to 32-bit values doesn't buy you anything.)
As the remarks to the DM_SETDEFID function note, messing directly with the default ID carelessly can lead to odd cases like a dialog box with two default buttons. Fortunately, you rarely need to change the default ID for a dialog.
A bigger problem is using SetFocus to shove focus around a dialog. If you do this, you are going directly to the window manager, bypassing the dialog manager. This means that you can create "impossible" situations like having focus on a pushbutton without that button being the default!
To avoid this problem, don't use SetFocus to change focus on a dialog. Instead, use the WM_NEXTDLGCTL message.
void SetDialogFocus(HWND hdlg, HWND hwndControl)
{
SendMessage(hdlg, WM_NEXTDLGCTL, (WPARAM)hwndControl, TRUE);
}
As the remarks for the WM_NEXTDLGCTL message observe, the DefDlgProc function handles the WM_NEXTDLGCTL message by updating all the internal dialog manager bookkeeping, deciding which button should be default, all that good stuff.
Now you can update dialog boxes like the professionals, avoiding oddities like having no default button, or worse, multiple default buttons! -
Some links on eLearning - [Everything]
2009-08-24
Resources on online learning
http://www.creatinglearningcommunities.org/
http://www.evergreen.edu/washcenter/project.asp?pid=73
http://carbon.ucdenver.edu/~mryder/dlc.html
http://www.thelearningcommunity.org/
http://www.inspiration.com/community/
http://www.webcosmo.com/listing/details.aspx?countryId=1&gId=5&postId=367328
http://blog.ala.asn.au/2009/08/community-engagement-30.html
http://www.gihanperera.info/2009/08/people-liked-e-learning-community.html
-
Microsoft is funny - [C++ sucks]
2009-07-28
In MFC Microsoft provided two string containers, CStringArray and CStringList. To retrieve the number of elements in it, on x86 you may use either GetSize or GetCount. However, on x64 for CStringList you should use GetCount and for CStringArray you should use GetSize.
It seems Microsoft is very clear about the difference between "count" and "size".
-
No MSN, GTalk, Skype, ICQ or Mobile, just MAIL - [Coder sucks?]
2009-07-28
Along with the rapid development of technology the ways for us to communicate with each other grows. We can call someone, send short messages, send emails, chat online with instanct messengers, or talk directly face to face. Each way listed here has both its advantages and its disadvantages and has a situation in which it's the first choice. For example, you are likely to send you application letter though email because by writting an email you have enough time to go though each word to make sure it shows your professionalism. Also an email requires no instance response and is easier to keep for future reference. Yes you might call the HR guy and read your application letter to him, but do this only when you are confident enough that you charming voice attracts him.
Today, in my presentation I won't do much comparision on various communication tools. Instead I'll suggest a old, good and forgoten way of communication, letters.
Letters have been popular for centuries until in recent years it's out of favor because of the rush of internet. Yes it has shortcommings. It's slow; it takes days to receive a response; Writting is not so easy as speaking directly; and sometimes your letter is just return back for some reason - anyway, i still suggest it. There's a story about it.
When I was a coledge student I have a friend, who is kind of shy. He likes math and video games. After graduation I got a job as a software engineer and he continued studying his master degree. At the time, he send email to me and another friend frequently. I seldom reply but he kept sending emails to us. In his emails he tell us things happened to our classmates, books he read recently, his plans, what makes him happy or sorry and sometimes his own compositions.
Afterward, at a night of black mood. I saw a new email from him and suddenly I decided to make a "BIG REPLY". I clicked "Reply" and began tell. I told my concern about future; what's making me unhappy; what I enjoy; what I'm pround of; what I want to change and what makes the upcomming change so difficult. When I was writting these I found the world was changing. I realized that the world is a wonderful one, there's much we can care about our friends. Yes Chun'Ge is funny but we wonder things on our friends more. Life is simple and interesting.
This remind me of the times when telephones were not popular and friends communicate mainly via letters. Writting a letter was always a nice experience then. Why with phones it's so different? I thought about it.
In a "instant communication" our focus is a very specific affair, while by writting a letter we are trying to have a deep digest on our life.
That's it.
-
What's Bing for? - [Coder sucks?]
2009-07-17
Actually I’ve never cared about Bing. 98% of my search is done via Google and I’ve got no plan to transfer. Anyway since Bing is kind of growing popular I think I may see what’s new in Bing.
Then I opened Bing.com. I was expecting a “cool new features” list but in its homepage I saw nothing. Then I searched “loose weight” with Bing in the hope of some minor surprise. To my disappointment, Bing is totally windows live search with a new strange name!
Sometimes changing name may make people a little bit more popular.
-
On solving problem first - [Coder sucks?]
2009-07-13
I’m not sure if it’s common but it happened to me. It was around 3 months ago, when I was assigned a task to ignore some illy defined observers in our simulator. The AE was very passionate and had great creativity. In his with description he easily extended the requirement from “Just ignoring bad observers” to
1. Adding a dialog for user to decide whether he’ll ignore the observer or abort the simulation
2. The choice can be saved so that in future the dialog won’t popup
3. There must be a application level option to change this optionWhen I got the wish I’m really surprised. The situation is not common; when a user is in the situation it’s always reasonable to ignore that observer, how could he be so unconstrained and extends the requirement so! At the time it was not convenient to communicate with the AE, so I asked my manager if we should try to “compress” the requirement.
“Well, I don’t think your attitude is good, it’s better solving a problem than shunning it!”
OK, as an employee it’s my duty to follow my manager. Also lacking of experience may limited my perspective of view and caused me being not able to distinguish “bad requirement” and “shunning a problem”. So I did as I was told.
Anyway now I still disagree what I was told.
Solving a problem is important only if the problem to solve is important. A company’s goal is not to solve problems, but to make money. Even the CPC is smart enough to say she’ll represent for “the most people”. A company should also solve problems that are critical to its most customers.
But that’s still the worst thing. Changing UI for very trivial requirement may confuse most customers. It makes software have more options and more annoying to configure. Inside the source codes have to be changed to reflect that requirement and as a result, our source code gets harder to maintain. We put effort in things that harms.
“Don’t disturb 98% for 2%’s special tastes!”
-
If you are bored by endless coding, there’re 8 decent reasons that’ll help you slack off. Each of them can earn you an at least 5 minutes break.
1. Get latest revision for all your local projects
2. If MSDN is not open, open it
3. Refactoring a member variable, a method or a class name
4. Rebuild All
5. Open a huge case from customers
6. Install latest update from Microsoft and restart Windows
7. Open a document from SharePoint, if you’re in a multinational company, open it from a server in another country
8. Search your computer for Does_not_exist.cpp -
Don’t be frighten away by the 4M “Hello World” - [C++ sucks]
2009-07-08
"I like WPF because it helps me build nice user interface. What I can’t bear is its huge program size. A simple ‘Hello World' takes up 4M disk size!"
True that a 4M hello world is big. True until you stop building “Hello Worlds” to your customers. What customers need usually is not a “Hello World”, they need you to simplify their very complicated business logic, they need your program to be safe and robust, they need nice-looking and easy-to-use UI, they need much more!
As you start adding features you customers asked for, you realized that there’s much provided in the 4M – there’s support for data accessing, imaging, user interface and threading; thread safety and network safety is taken care of; just everything is very handy! When the features are complete you found the program size has grown from 4M to 4.5M.
You come to think of before when you were using C, yes, the program had grown from 4K to 45M!
-
LRU Cache and shortest C++ implementation of it - [C++ Tricks]
2009-07-07
Every second there’s millions of queries processed by Baidu.com, is there any neat way to find the top 100 popular queries? This is the first problem in AStar 2009 2nd round.
My approach is to use a trie to record all words’ frequency, it’s accurate but it’s very slow. So for the problem I got 0 points. Later I asked others on the forum. “Well, actually the problem is asking you to design a cache that has high cache hit, I use LRU.” A guy said.
Stupid tactoth has no idea what a LRU is so he googled.
Well, the principle is easy, isn’t it? However until I saw someone mentioned implement it using three maps, I didn’t get any idea on how to implement it.
1: template<class K, class V>
2: struct lrumap
3: {4: typedef long long timestamp;
5: typedef typename __map<K, V> map_type;
6: typedef typename __map<K, timestamp> K2T;
7: typedef typename __map<timestamp, K> T2K;
8:9: map_type data;10: K2T k2t;11: T2K t2k;12:13: // fields
14: timestamp tm;15: size_type capacity;16: lrumap(size_type cap=10) { tm=1; capacity=cap;}17:18: size_type size(){ return data.size(); }
19: V& operator[](const K& k)
20: {21: timestamp& _tm=k2t[k];22: if(_tm)
23: t2k.erase(_tm);24: _tm=tm++;25: t2k[_tm]=k;26:27: V& ret=data[k];28:29: if(size()>capacity)
30: {31: K k=t2k.begin()->second;32: erase(k);33: }34: return ret;
35: }36: void erase(const K& k)
37: {38: t2k.erase(k2t[k]);39: k2t.erase(k);40: data.erase(k);41: }42: };With a LRU map the problem mentioned at begining of this article can easily be solved. It’s up to you to think why and how.
-
XXX when you have a full time job? - [Coder sucks?]
2009-07-07
As a software engineer, have you ever thought of get a master degree in software engineering, or a PMP certificate, or a MBA? I’m sure you have. However, most of us won’t do that.
Let’s be utilitarian, you need a certificate, or a higher degree for nothing else but more money, and be further you need more money for a higher quality life. Let’s put money first, for a software engineer, there’re several roads leading to more money; they are:
1. Promotion in career
2. Increasing of working experience
3. Hopping to another company
4. Do a part time job
5. Start your own business
Considering the goal that we are for a better life, to make more money at the sacrifice of your spare time that you originally may enjoy with your friends or family wouldn’t be a great idea. The extra work costs your energy and might influence your regular job, and thus will contribute you a no-so-good feedback. This harm you career.
If you do think you need to do something in your spare time, put these tips in mind:
1. The thing should be relaxing, you should fully enjoy it.
2. It should be able to help you keep a balance, in mental and physical, doing alone and doing with others, logistic and visual.
3. It helps you build a healthy lifestyle.
For me I found blogging a good way to kill part of my spare time. I tell my ideas on technical things or my life, exchange ideas with others. I share tricks, photos, and even games, websites. Recently I launch two blogs, one on technical issues and one on personal life. I’m planning to post programming, software design related topics on the first one, and photos I take on the second one. There’re reasons why I’ll benefit from blogging technical topics.
1. Build reputation in software industry and programmers, maybe I’ll be another Joel the other day J
2. Sharing knowledge and ideas in software development
3. Make money through advertisement – also applicable to “Life blog”
So the title should be : Blog when you are in a fulltime job
-
swap, a great performance booster! - [C++ Tricks]
2009-07-05
Recently I worked on a cpp code beatifier, it reads in a cpp file, analysis the content and beautify the format, then write the file back. In my code there's a function like this:
void beautify_a_file(const string& cpp_file)
{
string content;
// load the content
{
ifstream ifs(cpp_file.c_str());
string tmp((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
content=tmp; // this is bad, two large strings are constructed and then tmp is destroied
}
process(content);
// write it back
{
ofstream ofs(cpp_file.c_str());
ofs<<content;
}
}Let's look at the line content=tmp; this is a very time consuming operation, for the string here could be really big. A better way is to use string::swap, the method interchange of the two string's buffer ownership and no time-onsuming buffer copy is involved.
The fix: Change:
content=tmp;
to:
content.swap(tmp);
in <string> the std::swap is overloaded to be using string::swap, so you can also use:
std::swap(content, tmp);
Nearly all std containers have their own swap implementations, use them, instead of copy consructor!
-
auto_ptr is not that bad, use it! - [C++ Tricks]
2009-07-05
I've heard many people say auto_ptr is very error-proven. The main issue is the assign operator, for underlying it's a swap. I believe this is a design mistake too: auo_ptr should have disabled copy constructor and assign operator!
However besides the small issue, auto_ptr do can help avoid memory leaks, look at this code:
bool create_box(RECT rc)
{
box* pbox=new box(rc);
if(!pdocument->verify(pbox)) // a creation may not succeed on occasion
{
delete pbox; // it's very likely you'll miss this!
return false;
}
pdocument->add(pbox);
return true;
}Now let's make the code elegant and robust with auto_ptr:
bool create_box(RECT rc)
{
auto_ptr<box> pbox(new box(rc));
if(!pdocument->verify(pbox.get())) // a creation may not succeed on occasion
return false;
pdocument->add(pbox.release()); // transfer the ownership from local to the document
return true;
}Note this version is also exception-safe.
-
Totally rocks! -before I used this software I don't think NTFS has any advantage over FAT32. But now, I'm so impressed by the distinct indexing performance of NTFS.
The software changed the way I use windows, now I seldom use Windows Explorer!
Download it here.
-
View STL containers, MFC containers with autoexp.dat - [C++ Tricks]
2009-07-03
In visual studio 2005 and later Microsoft added a very neat and handy feature to their debugger. When you expand a vector in debugger, you won’t see:
+ std::_Vector_val<int,std::allocator<int> > {_Alval={...} } std::_Vector_val<int,std::allocator<int> >
+ _Myfirst 0x00383be0 int *
+ _Mylast 0x00383be4 int *
+ _Myend 0x00383be4 int *Instead you’ll see:
- vi [3](1,2,3) std::vector<int,std::allocator<int> >
[0] 1 int
[1] 2 int
[2] 3 intWell, this looks pretty good, but what if I want to expand my own container types?
First let’s see the definition for std::vector, find autoexp.dat with Everything, open it and search for "vector<*>", you’ll find this:
;------------------------------------------------------------------------------
; std::vector
;------------------------------------------------------------------------------
std::vector<*>{
children
(
#array
(
expr : ($e._Myfirst)[$i],
size : $e._Mylast-$e._Myfirst
)
)
preview
(
#(
"[", $e._Mylast - $e._Myfirst , "](",
#array
(
expr : ($e._Myfirst)[$i],
size : $e._Mylast-$e._Myfirst
),
")"
)
)
}This script is self documented well. I believe you’ve learnt how to add script to support your own containers, haven’t you?
-
Is scripting language faster than C++? - [C++ sucks]
2009-07-01
It started with a change I made on Tcl interpreter. At the time we need to embed Tcl into our products. Following the tutorial provided in Tcl's manual the integration is smoothy, but then we found each time after the application ended CRT detected plenty of memory leaks. I looked into the problem and was lucky enough to learn Tcl’s memory management algorithms.
Tcl use cache heavily to speedup memory allocation. It has around 12 buckets to hold memory blocks: bucket (0) holds blocks that has a size of 2^5; bucket (1) holds blocks that has a size of 2^6; …. The blocks in each bucket is managed with a linked list.Now suppose we are to allocate a memory block of size 50. First 50 is rounded up to 64, then it’ll go through the following logic to get the allocation done.
1. If there’s a block available in the 64 byte bucket, it’ll be removed from the bucket and returned.
2. If the bucket’s empty, it’ll try to find a block in a bigger bucket, here’s it’s the 128 byte bucket, and split the block returned to blocks of 64 bytes, add them to bucket for blocks of 64 bytes, and return one of them.
3. Biggest blocks are allocated directly from OS.
For multi-threaded applications there’ll be a cache for each thread, to reduce the time spent on acquiring the global heap lock.
Benefits of this memory management strategy:
1. All blocks are allocated at a fixed and large size; this help reduces the number of memory pieces.
2. Organize buckets into several levels is a much more efficient way than searching through the heap.
3. Yes the benefits of memory cache.
Let’s get back to the topic, why scripting languages can be faster than C++? For application developers they don’t care much about details of the platform, they just care what features the platform provide and what can they do with these features. Usually neither will a C++ write a GC for his application, nor will a Tcl developer modifying Tcl’s source code for his business logic. They use APIs, language features that’s natural from their existing knowledge of the platform. For memory allocation a C++ developer use “new” and “delete”, and a Tcl user use some “MALLOC” feature provide by Tcl. And we know the feature has been optimized by a smart design, which is likely to make the Tcl application faster than C++’s, at least at memory management aspect.
Conclusion:
1. C++ is a lower level language, not a faster language - there’re faster programs, but there’s no faster programming language!
2. For application developers, using some feature rich languages would be a better choice than C++, for these languages are not only “feature rich” but also “optimization rich”.
-
Separate new and constructor - [C++ Tricks]
2009-06-17
Look at this code:
string* ps=new string("hello, world");
As is know this code first allocate a memory block of sizeof(string), then call string’s constructor to "make the memory be a string object".
Seems C++ use this design to avoid memory being miss used, however there’re situations in which you want to separate the two, for example:
1. You just want to allocate some memory that can hold a string object, you don’t want to call its constructor immediately after the allocation.
2. You all ready have a block of memory, you want the constructor can be called on the memory you provide.
Well, simply this is possible:
{
string* ps=(string*)(::operator new(sizeof(string))); // this allocate memory for a string
::new(ps) string("hello, world"); // call constructor of string on ps
t->~TS(); // call its destructor without free the memory
::operator delete(t); // free the memory
} -
Yes, no loop, no EOF test. Just one line:
ifstream ifs("test.txt");
string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>()); -
Fix memory leaks in 5 minutes - [C++ Tricks]
2009-01-13
Does memory leaks?
#include <crtdbg.h>
void main()
{
_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
int* leak = new int[10];
}Press F5 to run it, after the execution you get this in output window:
Detected memory leaks!
Dumping objects ->
{52} normal block at 0x003C4410, 40 bytes long.
Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.Locate the leak
You know there’s memory leak. Now it’s time to locate the code that caused it.
Let’s look at this line in the output after the previous execution:{52} normal block at 0x003C4410, 40 bytes long.
The 52 means this leak is allocated in the 52nd allocation. We can use _CrtSetBreakAlloc to make CRT break at that allocation.
void main()
{_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF);
_CrtSetBreakAlloc(52);
int* leak = new int[10];
}
You’ll see the program break and enter debugging mode when it runs to int* leak = new int[10]. You may realize how useful this information is. However in multithreaded programs this doesn’t work because the turn of allocation may vary although the workflows you see are same.









