miércoles, 17 de abril de 2013

#pragma pack

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

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;
}

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


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
class Base 
{
    // some virtual methods
};

class Derived : public Base
{
    ~Derived()
    {
        // Do some important cleanup
    }
}
What happens if we do the following?


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

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/