Two days dealing with a bug and finally I realized I missed one #pragma pack declaration! It was an alignment problem.
Damn it!
http://msdn.microsoft.com/en-us/library/2e70t5y1(v=vs.80).aspx
David Orejuela's Blog
Software Engineering
miércoles, 17 de abril de 2013
miércoles, 27 de marzo de 2013
Modeless dialogs Vs.TAB key, arrow keys, and accelerator keys (II)
I think the last solution is an overkill. Remember what was the problem:
In some point the pump gets the modeless window handler and it is not able to get the corresponding window to call the PreTranslateMessage member funcion.
BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg)
{
...
for (HWND hWnd = pMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
{
//FromHandlePermanent will return NULL, causing our issue
CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
if (pWnd != NULL)
{
if (pWnd->PreTranslateMessage(pMsg))
return TRUE;
}
}
...
}
So we put a hook to the thread, the result: thousands of callings to our PreTranslateMessage member funcion with another thousand messages being delivered through the hook.
So I was doing some researching and I found the IsDialogMessage function:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms645498(v=vs.85).aspx
It determines whether a message is intended for the specified dialog box and, if it is, processes the message. So we can do the following in our CWinApp derived class:
BOOL YourCWinApp ::PreTranslateMessage(MSG* pMsg)
{
switch (pMsg->message)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
{
CWnd *pWndPermanent = CWnd::FromHandlePermanent(pMsg->hwnd);
//If FromHandlePermanent returns NULL then it should be a control of a modeless windows
//or a modeless window itself.
if (!pWndPermanent && pMsg->hwnd)
{
//If it's a control inside the modeless window, we have to get the top parent
HWND hTopParent= AppGetTopParent(pMsg->hwnd);
return IsDialogMessage(hTopParent, pMsg);
}
}
}
return CRazorEXE::PreTranslateMessage(pMsg);
}
HWND AppGetTopParent(HWND hWnd)
{
#define APP_IsSet(flag, flagToTest) ((flag&(flagToTest))==(flagToTest))
#define APP_GetWindowStyle(hwnd) ((LONG_PTR)(GetWindowLongPtr(hwnd, GWL_STYLE)))
#define APP_IsChildWindow(hwnd) APP_IsSet(APP_GetWindowStyle(hwnd), WS_CHILD)
if(hWnd == NULL)
return NULL;
HWND hWndParent = hWnd;
while(hWndParent != NULL && APP_IsChildWindow(hWndParent) == TRUE)
hWndParent = ::GetParent(hWndParent);
return hWndParent;
}
In some point the pump gets the modeless window handler and it is not able to get the corresponding window to call the PreTranslateMessage member funcion.
BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg)
{
...
for (HWND hWnd = pMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
{
//FromHandlePermanent will return NULL, causing our issue
CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
if (pWnd != NULL)
{
if (pWnd->PreTranslateMessage(pMsg))
return TRUE;
}
}
...
}
So we put a hook to the thread, the result: thousands of callings to our PreTranslateMessage member funcion with another thousand messages being delivered through the hook.
So I was doing some researching and I found the IsDialogMessage function:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms645498(v=vs.85).aspx
It determines whether a message is intended for the specified dialog box and, if it is, processes the message. So we can do the following in our CWinApp derived class:
BOOL YourCWinApp ::PreTranslateMessage(MSG* pMsg)
{
switch (pMsg->message)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
{
CWnd *pWndPermanent = CWnd::FromHandlePermanent(pMsg->hwnd);
//If FromHandlePermanent returns NULL then it should be a control of a modeless windows
//or a modeless window itself.
if (!pWndPermanent && pMsg->hwnd)
{
//If it's a control inside the modeless window, we have to get the top parent
HWND hTopParent= AppGetTopParent(pMsg->hwnd);
return IsDialogMessage(hTopParent, pMsg);
}
}
}
return CRazorEXE::PreTranslateMessage(pMsg);
}
HWND AppGetTopParent(HWND hWnd)
{
#define APP_IsSet(flag, flagToTest) ((flag&(flagToTest))==(flagToTest))
#define APP_GetWindowStyle(hwnd) ((LONG_PTR)(GetWindowLongPtr(hwnd, GWL_STYLE)))
#define APP_IsChildWindow(hwnd) APP_IsSet(APP_GetWindowStyle(hwnd), WS_CHILD)
if(hWnd == NULL)
return NULL;
HWND hWndParent = hWnd;
while(hWndParent != NULL && APP_IsChildWindow(hWndParent) == TRUE)
hWndParent = ::GetParent(hWndParent);
return hWndParent;
}
miércoles, 13 de marzo de 2013
Modeless dialogs Vs.TAB key, arrow keys, and accelerator keys
This is something I had to fix some days ago with a modeless dialog, I spent half hour trying to figure out why the PreTranslateMessage wasn't being called. Finally I found out a solution:
http://support.microsoft.com/kb/q187988
After that the PreTranslateMassage will be called. To manage the key states in the PreTranslateMassage should be enough, something like this:
BOOL CFuncViewFindDialog::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN)
{
SHORT nReturnDown = GetKeyState(VK_RETURN) & 0x8000;
SHORT nTabDown = GetKeyState(VK_TAB) & 0x8000;
if (nReturnDown)
{
//Your stuff
http://support.microsoft.com/kb/q187988
After that the PreTranslateMassage will be called. To manage the key states in the PreTranslateMassage should be enough, something like this:
BOOL CFuncViewFindDialog::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN)
{
SHORT nReturnDown = GetKeyState(VK_RETURN) & 0x8000;
SHORT nTabDown = GetKeyState(VK_TAB) & 0x8000;
if (nReturnDown)
{
//Your stuff
viernes, 1 de febrero de 2013
Virtual destructors
http://www.gotw.ca/publications/mill18.htm
Virtual destructors are useful when you can delete an instance of a derived class through a pointer to base class
Virtual destructors are useful when you can delete an instance of a derived class through a pointer to base class
What happens if we do the following?class Base { // some virtual methods }; class Derived : public Base { ~Derived() { // Do some important cleanup } }
Base *b = new Derived();
// use b
delete b; // Here's the problem! Since Base's destructor is not virtual,
// it's ~Base that is called and not ~Derived. Therefore, all the important
// cleanup is not performed, which can create several resource leaks
jueves, 13 de diciembre de 2012
C++11 (I)
What's new in C++11?
Auto and decltype
Use auto for type deduction (C++11 use same type deduction as function templates)
auto i = 3; //i has type int
auto &r = i; //r has type int&
decltype (i) j; //j has type int (named variable)
decltype ((i)) k; //k has type int& (lvalue)
//C++03
std::vector<int> vec;
for (std::vector<int>::iterator i = vec.begin();i != vec.end(); ++i);
//C++11
for (auto i = vec.begin(); i!+ vec.end(); ++i);
int arr[10];
for (auto i = std::begin(arr); i != std::end(arr); ++i);
Auto and functions
// C++03 - What should be the return type of add?
template <typename T1, typename T2>
??? add(T1 t1, T2 t2)
{
return t1+t2;
}
//C++11
template <typename T1, typename T2>
auto add(T1 t1, T2 t2) -> decltype(t1 + t2)
{
return t1+t2;
}
Uniform initialisation
Arrays
// C++03 and C++11
int a[] = { 1, 3 };
std::vectors
// C++03
std::vector<int> v;
v.push_back(1);
v.push_back(3);
// C++11
sstd::vector<int> v{ 1, 3 };
Structs
//C++03
struct X {
int i, j;
X (int i, int j) : i(i), j(j) {}
};
X x(3,4);
//C++11
struct X {
int i, j;
};
X x{3, 4}
std::initializer_list
// C++11
class X {
public:
X(std::initializer_list<int> lst) {
for (auto i : lst)
v.push_back(i);
}
private:
std::vector<int> v;
};
X x = { 1, 4, 7 }; // equivalent
X x2{ 3, 6, 9 };
void f(std::initializer_list<float> l);
f({ 2.3, 4.0 });
// can also be used as return value from a function
struct Y { int a, b; };
Y y = { 1.2, 3 }; // error, narrowing conversion
Range based for loop
// C++11
std::vector<int> vec;
for (auto & i : vec)
i++;
for (auto i : { 1, 4, 7 }) {}
int arr[] = { 3, 9, 12, 15 };
for (auto i : arr)
std::cout << i << std::endl;
std::map<int, int> m {
{1, 2}, {3, 4}, {5, 6}
};
for (const auto & pr : m)
std::cout << pr.first << “ “ << pr.second << std::endl;
Constructing and initialisation
// C++11
struct X {
int i = 4;// yay, just like other languages!
int j{5}; // equivalent form using uniform initialisation
};
Controlling special members functions
// C++03
struct NotCopyable {
private:
// declared but
// not implemented
NotCopyable(
const NotCopyable &);
NotCopyable & operator=(
const NotCopyable &);
};
// copying NC => linker error
struct X {
Y y;
X(int i) : y(i) {}
X(): y() {} // manual
};
// C++03
struct NotCopyable {
private:
// declared but
// not implemented
NotCopyable(
const NotCopyable &);
NotCopyable & operator=(
const NotCopyable &);
};
// copying NC => linker error
struct X {
Y y;
X(int i) : y(i) {}
X(): y() {} // manual
};
// C++11
struct NotCopyable {
NotCopyable(
const NotCopyable &) = delete
NotCopyable & operator=(
const NotCopyable &) = delete;
};
// copying NC => compiler error
// “friendly” deleted function msg
struct X {
Y y;
X(int i) : y(i) {}
X() = default; // compiler’s
};
// C++11
struct NotCopyable {
NotCopyable(
const NotCopyable &) = delete
NotCopyable & operator=(
const NotCopyable &) = delete;
};
// copying NC => compiler error
// “friendly” deleted function msg
struct X {
Y y;
X(int i) : y(i) {}
X() = default; // compiler’s
};
miércoles, 5 de diciembre de 2012
Interesting Macro (without branch or compares) to Increment And Decrement Wrapping Values
For processors where compare and branch is very expensive, to use in critical code:
#define DECL_WRAP_INC( type_name, type, stype, bit_mask )
static inline type wrap_inc_##type_name( const type val, const type min, const type max )
{
const type result_inc = val + 1;
const type max_diff = max - val;
const type max_diff_nz = (type)( (stype)( max_diff | -max_diff ) >> bit_mask );
const type max_diff_eqz = ~max_diff_nz;
const type result = ( result_inc & max_diff_nz ) | ( min & max_diff_eqz );
return (result);
}
From http://cellperformance.beyond3d.com/articles/2006/07/increment-and-decrement-wrapping-values.html#more
#define DECL_WRAP_INC( type_name, type, stype, bit_mask )
static inline type wrap_inc_##type_name( const type val, const type min, const type max )
{
const type result_inc = val + 1;
const type max_diff = max - val;
const type max_diff_nz = (type)( (stype)( max_diff | -max_diff ) >> bit_mask );
const type max_diff_eqz = ~max_diff_nz;
const type result = ( result_inc & max_diff_nz ) | ( min & max_diff_eqz );
return (result);
}
From http://cellperformance.beyond3d.com/articles/2006/07/increment-and-decrement-wrapping-values.html#more
Macro definitions and #,##
Function macro definitions accept two special operators (# and ##) in the replacement sequence:
If the operator # is used before a parameter is used in the replacement sequence, that parameter is replaced by a string literal (as if it were enclosed between double quotes)
#define str(x) #x
cout << str(test);
This would be translated into:
cout << "test";
The operator ## concatenates two arguments leaving no blank spaces between them:
#define glue(a,b) a ## b
glue(c,out) << "test";
This would also be translated into:
cout << "test";
From http://www.cplusplus.com/doc/tutorial/preprocessor/
Suscribirse a:
Entradas (Atom)