0
votes

MFC C++ project under MS VS2015. My plan is to dynamically create lots of (say >200) CStatic boxes using the extended styles: WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE to make them look nice. It means I can’t use CStatic::Create, instead using:

DWORD style = WS_VISIBLE | WS_CHILD | SS_CENTER | SS_NOTIFY;

p->box = CreateWindowEx(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE, "STATIC", nStr, style,
         p->posX, p->posY, p->sizeX, p->sizeY, this->GetSafeHwnd(), NULL, GetModuleHandle(nullptr), NULL );

It would be very convenient to find out if one of the static windows has been clicked so I set the SS_NOTIFY style. According to the docs I should get an STN_CLICKED notification, which is great. But this apparently goes through the WM_COMMAND message.

WM_COMMAND is not listed as an available message in the parent dialog properties.

If I manually create a static box in the parent dialog, and set the Notify property as true, I can get an STN_CLICKED handler which neatly goes in to the message map macro:

ON_STN_CLICKED( IDC_TEST, &CFamilyDlg::OnStnClickedTest )

Since I am dynamically creating the boxes, I can’t put one handler in for each static window. (In any case the CreateWindowEx function generates an HWND rather than having a control ID.)

I want to receive all STN_CLICKED messages, then use the HWND to tell me which one is active so I can do something about it.

Thoughts?

1
Would look at something like ON_CONTROL_RANGE(STN_CLICKED, STID_MIN, STID_MAX, &YourFunc); Google for ON_CONTROL_RANGE(). If that doesnt work, try ON_NOTIFY_RANGE - Joseph Willcoxson
Thanks @Joseph, that works nicely now. - analog

1 Answers

0
votes

Following on from Joseph Willcoxson’s comment, I have added IDs to the dynamically created static boxes. (Just some random range for now)

DWORD style = WS_VISIBLE | WS_CHILD | SS_CENTER | SS_NOTIFY;
p->box = CreateWindowEx(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE, "STATIC", nStr, style, p->posX, p->posY, p->sizeX, p->sizeY,
             this->GetSafeHwnd(), NULL, GetModuleHandle(nullptr), NULL );

CWnd* pWnd = CWnd::FromHandle(p->box);
pWnd->SetDlgCtrlID( 0x1000 + idx);

Then a handler function:

afx_msg void OnPersonClicked( UINT nID );

And the suggested message map entry:

ON_CONTROL_RANGE(STN_CLICKED, 0x1000, 0x2000, OnPersonClicked )

which now works as required :-)

The only difference for the real code is to add a couple of constants:

const int MIN_ID = 0x1000; const int MAX_ID = 0x2000;

I didn't use an ampersand in front of the function name, but it works with or without it.