CSpinButtonCtrl: How to remove Autobuddy style? - windows

I use a CSpinButtonCtrl, the AutoBuddy Style is set in the DialogResssource to TRUE.
I must now remove/hide the CSliderButtonCtrl in KioskMode (FullScreen).
I have tried this, it is not enough, the associated CEditCtrl does not redraw, the place where the SpinCtrl was.
CMyFormView::OnInitialUpdate()
{
if (g_bKiosMode)
{
m_ctlSpin1.ShowWindow(SW_HIDE);
m_ctlSpin1.ShowWindow(SW_ENABLE);
LONG style = GetWindowLong(m_ctlSpinSollwert1.GetSafeHwnd(), GWL_STYLE);
style &= ~UDS_AUTOBUDDY;
SetWindowLong(m_ctlSpinSollwert2.GetSafeHwnd(), GWL_STYLE, style);
}
}
}
tried too:
if (!g_bKioskMode)
{
DDX_Control(pDX, IDC_SPIN1, m_ctlSpin1);
}
tried too: Subclass the CSpinCtrl, but the PreCreateWindow(..) is not called
class CMySpinButton : public CSpinButtonCtrl
{
DECLARE_DYNAMIC(CMySpinButton)
public:
CMySpinButton();
virtual ~CMySpinButton();
protected:
DECLARE_MESSAGE_MAP()
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
};
further ideas?

You can detach a Up-Down control by sending it the UDM_SETBUDDY message with a NULL HWND and then hiding the window.
The Up-Down control will actually resize its buddy so you need to resize the edit control after you have detached.

Related

MFC - encountering deadly diamond of death

A newbie here in windows programming.
I want to make a dialogbox that uses both CPropertyPage and CDHtmlDialog?
class CPropertyPage : public CDialog
class CDHtmlDialog : public CDialog
Since I can't change the inheritance for each of the above case to "virtual public", is it still possible to make a dialog that has some fields from CPropertyPage and some forms from CDHtmlDialog?
You can create the HTML dialog as child dialog of property page. The only problem is that child dialog closes if user pressed cancel. You have to override CDHtmlDialog::OnCancel. Example:
class CMyDHtmlDialog : public CDHtmlDialog
{
void OnCancel()
{
//GetParent()->GetParent()->PostMessage(WM_COMMAND, IDCANCEL);
}
};
class CMyPropertyPage : public CPropertyPage
{
CMyDHtmlDialog child;
BOOL OnInitDialog()
{
BOOL res = CPropertyPage::OnInitDialog();
child.Create(IDD_HTML, this);
CRect rc;
GetClientRect(&rc);
child.SetWindowPos(NULL, 0, 0, rc.Width(), rc.Height(), SWP_SHOWWINDOW);
return res;
}
};

Forcing a combobox to "dropdown" above instead of below

When you click on the "dropdown" button of a combobox, the dropped down listbox appears below the combobox, unless there is not enough space below, in which case the listbox appears above.
Now I wonder if there is a possibility to force the lisbox to appear above the combobox, even if there is enough space below.
Illustration
When I click on the combo box, I'd like the "drop down" list box appear always above as on the left screen copy.
Everything is possible, and you don't need to implement the control "from scratch".
First, you can subclass the ListBox part of your ComboBox to get complete control over it, as explained in MSDN. You can create a class, derived from CListBox, using the Class Wizard. You only need to implement WM_WINPOSITIONCHANGING handler in it:
void CTopListBox::OnWindowPosChanging(WINDOWPOS* lpwndpos)
{
CListBox::OnWindowPosChanging(lpwndpos);
if ((lpwndpos->flags & SWP_NOMOVE) == 0)
{
lpwndpos->y -= lpwndpos->cy + 30;
}
}
Here, for simplicity, I am moving the box up by the (heights+30). You can get the height of your ComboBox instead of my 30.
Then you declare a member variable in your dialog class:
CTopListBox m_listbox;
and subclass it like that:
HBRUSH CMFCDlgDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
if (nCtlColor == CTLCOLOR_LISTBOX)
{
if (m_listbox.GetSafeHwnd() == NULL)
{
m_listbox.SubclassWindow(pWnd->GetSafeHwnd());
CRect r;
m_listbox.GetWindowRect(r);
m_listbox.MoveWindow(r);
}
}
HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
return hbr;
}
Note that I am calling m_listbox.MoveWindow(r) there; it is needed because first WM_CONTROLCOLOR message for that list box comes after it is positioned, so the very first time it would drop down instead of up.
Disclaimer: this is not a very clean solution, as, if you have windows animation enabled, you'd see that the list unrolls from top to bottom.
Alternatively, you should be able to "fool" the combobox that it is too close to the bottom of the screen; then it will drop up by itself. I leave it as an exercise for the readers :)
This would be relatively easy except when combo box has "slide open" effect. If you move the dropdown listbox to the top, and the combo slides open from top-to-bottom, it would look odd. So you have to disable the animation or reverse it.
In this function I call AnimateWindow in OnWindowPosChanging, it doesn't seem to cause any problems but I am not a 100% sure about it!
class CComboBox_ListBox : public CListBox
{
public:
CWnd *comboBox;
void OnWindowPosChanging(WINDOWPOS *wndpos)
{
CListBox::OnWindowPosChanging(wndpos);
if (comboBox && wndpos->cx && wndpos->cy && !(wndpos->flags & SWP_NOMOVE))
{
CRect rc;
comboBox->GetWindowRect(&rc);
//if listbox is at the bottom...
if (wndpos->y > rc.top) {
//if there is enough room for listbox to go on top...
if (rc.top > wndpos->cy) {
wndpos->y = rc.top - wndpos->cy;
BOOL animation;
SystemParametersInfo(SPI_GETCOMBOBOXANIMATION, 0, &animation, 0);
//if combobox slides open...
if (animation) {
//we have to set the x coordinate otherwise listbox
//is in the wrong place when parent window moves
SetWindowPos(0, wndpos->x, wndpos->y, 0, 0,
SWP_NOSENDCHANGING | SWP_HIDEWINDOW | SWP_NOSIZE);
AnimateWindow(100, AW_VER_NEGATIVE);
}
}
}
}
}
DECLARE_MESSAGE_MAP()
};
Usage:
COMBOBOXINFO ci = { sizeof(COMBOBOXINFO) };
comboBox.GetComboBoxInfo(&ci);
CComboBox_ListBox *listBox = new CComboBox_ListBox;
listBox->comboBox = &comboBox;
listBox->SubclassWindow(ci.hwndList);
Also you can use SetMinVisibleItems to reduce the listbox height and make sure the dropdown list fits on top.

CListCtrl set font style to bold

I want to change font of any cell of CListCtrl control to bold. Can any one tell how to do it for CList Ctrl.
I have already done this for a CTreeCtrl, like this
pTC->SetItemState(hItemCur, TVIS_BOLD, TVIS_BOLD);
do we have something similar for CListCtrl?
Thanks in advance.
If you can use CMFCListCtrl (VS2008 SP1 and up), you can derive a class from it and override OnGetCellFont. From there you return your bold font (you can create your own or return AFX_GLOBAL_DATA::fontBold):
HFONT CMyListCtrl::OnGetCellFont( int nRow, int nColumn, DWORD dwData /*= 0*/ )
{
if (UseBoldFont(/* params */))
{
return GetGlobalData()->fontBold;
}
return NULL;
}
If you have to stick to plain old CListCtrl, the easiest way would be to use Custom Draw, where you can tweak the drawing process to your own needs. Don't confuse it with Owner Draw, where you have to do all the drawing yourself.
Here's an article explaining the basics of using Custom Draw with CListCtrl.
Add
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomdraw)
to your message map.
Now you can simply modify items as you wish in this function. In here you can change the align, font, background-color, text-color, [...], and you can set items to bold -> example. The best way IMO, is to either store a pointer to a struct, class or simply a flag in the LPARAM of the item(s) in the control. This function works for both CListCtrl and CTreeCtrl.
Here is an example with flags:
enum ColorFlags
{
F_COLOR_BLACK = 0x1,
F_COLOR_WHITE = 0x2
//and more...
};
enum CustomColors
{
COLOR_BLACK = RGB(0, 0, 0),
COLOR_WHITE = RGB(255, 255, 255)
};
afx_msg
void CMyListCtrl::OnCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
NMLVCUSTOMDRAW *pDraw = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);
switch (pDraw->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
*pResult = CDRF_NOTIFYITEMDRAW; //Do not forget this...
break;
case CDDS_ITEMPREPAINT:
{
switch (pDraw->nmcd.lItemlParam) //Extract color from flags
{
case F_COLOR_BLACK:
{
pDraw->clrText = COLOR_BLACK;
} break;
case F_COLOR_WHITE:
{
pDraw->clrText = COLOR_WHITE;
} break;
default:
break;
} //switch
} break;
} //switch
}

firebreath plugin create a full screen window, but the window always under the browser window when it appers, how can I bring it to top

CaptureScreenApp app;
int MyPluginAPI::captureScreen(const FB::JSObjectPtr& callback)
{
boost::thread cs(boost::bind(&CaptureScreenApp ::captureScreen,
app, callback));
return 1;
}
class CaptureScreenApp {
public:
CaptureScreenApp() {
HRESULT hRes;
hRes = OleInitialize(NULL);
ATLASSERT(SUCCEEDED(hRes));
AtlInitCommonControls(ICC_WIN95_CLASSES);
g_Module.Init(NULL, NULL);
};
~CaptureScreenApp() {
g_Module.Term();
OleUninitialize();
};
bool captureScreen() {
CMessageLoop theLoop;
CMainDialog g_MainDlg;
g_Module.AddMessageLoop(&theLoop);
if (NULL == g_MainDlg.Create(NULL)){
DWORD ret = GetLastError();
return FALSE;
}
g_MainDlg.ShowWindow(SW_SHOW);
g_MainDlg.UpdateWindow();
int nRet = theLoop.Run();
g_Module.RemoveMessageLoop();
return TRUE;
};
};
class CMainDialog : public CDialogImpl<CMainDialog>
{
public:
enum {IDD = IDD_MAIN};
....
}
the window(the new window is a full screen window with a desktop pic as the background) I create in CaptureScreenApp::captureScreen always under the browser window when it appears(browser window always actived in other word), what ever how I set the HWND_TOPMOST for the new window. like this:
enter link description here
how can i bring the full screen window to top when it appers?
SetWindowPos API lets you change Z order (make sure to read Remarks there). You create your window with NULL parent, so your window is completely independent from browser window, so there is nothing to push it to the front: it would be either you or interactive user.

How do I limit mouse pointer movement in wxWidgets?

Is there a way to limit mouse pointer movement to a specific area in wxWidgets? I know there is an API function ClipCursor() in Windows, but is there a method in wxWidgets for all platforms?
No. There is no such function in wx by all i know. Start up a timer (say 50ms) checking the global mouse position. If the mouse is outside the region, then set it into again.
If you want to restrict the mouse for some certain reason, for example to make some sort of game, then you can capture the mouse (see wxWindow::CaptureMouse). You will get mouse events even if the pointer is outside your window. Then you could react to mouse-motion events and do the check for the position there, without a timer. Downside of this is that the mouse won't be able to be used somewhere else for other programs since they won't receive events.
wxWidgets manual states that OSX guidelines forbid the programs to set the mouse pointer to a certain position programmatically. That might contribute to the reason there is not much support for such stuff in wx, especially since wx tries really hard to be compatible to everything possible.
Small sample. Click on the button to restrict the mouse to area 0,0,100,100. Click somewhere to release it.
#include <wx/wx.h>
namespace sample {
class MyWin : public wxFrame {
public:
MyWin()
:wxFrame(0, wxID_ANY, wxT("haha title")) {
mRestricted = wxRect(0, 0, 100, 100);
mLast = mRestricted.GetTopLeft();
wxButton * button = new wxButton(this, wxID_ANY, wxT("click this"));
}
private:
void OnClicked(wxCommandEvent& event) {
if(!HasCapture()) {
CaptureMouse();
CheckPosition();
}
}
void OnMotion(wxMouseEvent& event) {
CheckPosition();
}
void OnLeft(wxMouseEvent& event) {
if(HasCapture())
ReleaseMouse();
}
void CheckPosition() {
wxPoint pos = wxGetMousePosition();
if(!mRestricted.Contains(pos)) {
pos = ScreenToClient(mLast);
WarpPointer(pos.x, pos.y);
} else {
mLast = pos;
}
}
wxRect mRestricted;
wxPoint mLast;
DECLARE_EVENT_TABLE();
};
BEGIN_EVENT_TABLE(MyWin, wxFrame)
EVT_BUTTON(wxID_ANY, MyWin::OnClicked)
EVT_MOTION(MyWin::OnMotion)
EVT_LEFT_DOWN(MyWin::OnLeft)
END_EVENT_TABLE()
class MyApp : public wxApp {
virtual bool OnInit() {
MyWin * win = new MyWin;
win -> Show();
SetTopWindow(win);
return true;
}
};
} /* sample:: */
IMPLEMENT_APP(sample::MyApp)

Resources