CListBox's Item size changed when changing the size of the list box even if I specify the size in MeasureItem() method? - mfc

I used a class which derives from CListBox, and create it with following:
style:WS_CHILD|WS_VISIBLE |LBS_OWNERDRAWFIXED | WS_VSCROLL | WS_HSCROLL
I expect the ListBox's item to be have a fixed size, not affected by the size of the list box. So I override the MeasureItem() method, in which I specify the item's size like below:
void CMyListBox::MeasureItem(LPMEASUREITEMSTRUCT lpMIS)
{
lpMIS->itemHeight = ALBUM_ITEM_HEIGHT;
lpMIS->itemWidth = ALBUM_ITEM_WIDTH;
}
But the item's size changes according to the List box's size changing. is there anything wrong with my approach?

What's not mentioned in the reference is that WM_MEASUREITEM is called every time the *_OWNERDRAWFIXED control is resized.
I don't know however, how official this behavior is and whether it should be relied on, but it has been verified at CodeGuru and several forum posts found on the Google thing.
If you don't want to process the message, then just set a private flag somewhere in the first OnMeasureItem() call and return from it as soon as you check that it's set next time.

If you look at the MSDN entry for CListBox::MeasureItem you'll see that it's only called once unless the LBS_OWNERDRAWVARIABLE (not LBS_OWNERDRAWFIXED) style is set. If I understand correctly then this would explain the behaviour you're seeing because MeasureItem would need to be called each time the control's size changes.
Also, have you considered the points made in MFC Technical Note 14 : Custom Controls?

Related

How to get the currently selected text in a CComboBoxEx?

My first approach to the problem was to call the GetWindowsText method on the CComboBoxEx control, but I found that there is no associated text. After analyzing the control with Spy++ and reading some documentation on CComboBoxEx, I realised that these type of controls are only the parent of a classic ComboBox:
I tried using the GetLBText() method on the child ComboBox, passing GetCurSel() as an argument, but I only get some wrong text (the correct text should be "English"):
Am I missing something? Thanks in advance!
What you want to do is map the control to a int variable using Class Wizard:
Now it is easy to access the selected text at any time. You need to use the GetItem function. For example (code not tested):
COMBOBOXEXITEM cmbItem;
CString strText;
cmbItem.mask = CBEIF_TEXT;
cmbItem.iItem = m_cbItemIndex;
cmbItem.pszText = strText.GetBuffer(_MAX_PATH);
m_cbMyCombo.GetItem(&cmbItem);
strText.ReleaseBuffer();
In short, you need to use the COMBOBOXEXITEM and initialise it with the right flags to state what information you want to get from the extended combo. That, and the item index. Job done!
I realise that you have your own inherited class, but the mechanics are the same. You don't use GetLBText. You use the structure with the index and GetItem to get the selected text.
In the end I managed to retrieve the correct name; as you can see in the image below, the ComboBox is only a child of a CombBoxEx32:
I retrieved the pointer to the parent ComboBoxEx32 from the child ComboBox, and searched for the text this way:
CString szText;
CComboBoxEx cbParentCombo ;
cbParentCombo.Attach( GetParent()->GetSafeHwnd()) ;
cbParentCombo.GetLBText( GetCurSel(), szText) ;
cbParentCombo.Detach() ;
My mistake was that I was calling GetLBText() directly from the child ComboBox, instead of the parent CComboBoxEx; because of that, all I was getting was some random gibberish. GetLBText() was indeed the correct solution.

How to get the text value of a control through its parent window

I have the following wxDialog parent window:
I have created that parent window by the following code:
settingsFrm settingsWindow(this, "Settings");
settingsWindow.ShowModal();
I have tried to use FindWindowByName to get the value of the first text ctrl as follow:
wxLogMessage(dynamic_cast<wxTextCtrl*>(settingsWindow->FindWindowByName("keywords_txt"))->GetValue());
But unfortunately, it doesn't work and gives me a runtime error.
I don't know if that method suitable to do what I want.
How to get the value/other of a control through its parent window?
From your comments, it seems like you expect the function to find the control from the name of the variable in your code which is not how it works and would be pretty much impossible.
FindWindowByName() uses the window name (and, as a fallback, label, but this is irrelevant here because text controls don't have labels anyhow), so for it to work you need to set the window name when creating the control, using the corresponding parameter of its ctor. This is very rarely useful in C++ code, however, as it's simpler to just store a pointer to the control in some variable and use this instead.
FindWindowByName() can often be useful when creating controls from XRC, however. If you do this, then you should specify names for your controls in XRC and pass the same name to this function.
How did you create the TextCtrl instance? You should have something like wxTextCtrl m_textCtrl1 = new wxTextCtrl(/// arguments); Accessing the value should be very easy, as wxString text = m_textCtrl1->GetValue(); You definitely don't need FindWindowByName just for what you are trying to do here.

Qt QWidget::minimumSizeHint delay (#2)

When i hide a widget in my application, the minimumSizeHint isn't updated immediatly.
I tried the QLayout::activate() solution suggested at this post, but it doesn't work for me because QLayout::activate() returns false.
I try to do it at MainWindow class like this:
ui.groupBox->setVisible(!ui.groupBox->isVisible());
qDebug() << this->layout()->activate();
qDebug() << this->minimumSizeHint();
this->resize(this->minimumSizeHint());
Any ideas why it's not working?
My current workaround is:
QTimer::singleShot(10, this, SLOT(on_resizeMin()));
but i noticed 10ms may not be enough on a slow system. Nasty workaround.
The size hints are meant to be used at appropriate moments by the layout system. You're not supposed to be using them elsewhere - that's why they appear to "not work".
You appear to want to constrain the size of the main widget (the window) to one of the size hints. You'll need to set an appropriate sizeConstrainton that widget's layout. There are two approaches:
Use the QLayout::SetFixedSize constraint. Reimplement the layout's sizeHint to return minimumSize, such that the QLayout::SetFixedSize will set the window's size to the minimum size hint, not the default size hint.
Patch Qt to implement QLayout::SetMinAndMaxToMinSize, meaning "The main widget's minimum and maximum size are set to minimumSize()"
The patch is small :)

XLib - Window hints behave differently when I construct XWindowAttributes in the main function?

I am experimenting with some fundamental Xlib stuff. I am creating a basic window and creating an OpenGL context for it.
I am trying to prevent the user from being able to resize or manually full screen the window. I added the code:
XSizeHints hints;
hints.min_width = hints.max_width = setup.w;
hints.min_height = hints.max_height = setup.h;
XSetWMNormalHints(dpy, win, &hints);
This worked at first. However after experimenting with it I have found that it mysteriously stops working sometimes. It is not a matter of unusual window managers or anything like that, I am using the default windows manager installed with Ubuntu. What causes it to change, strangly enough, is whether or not I include this line in main:
XWindowAttributes atts;
It does not matter where I put it. At the beginning, or inside a loop, or even after the return. As long as I put that somewhere in main the hints prevent resizing (just to be clear, any name for the variable works). It does not matter if I use it at all or not, it was initially there for a call to XGetWindowAttributes. I discovered the problem when I tried moving that into a separate function call. If I take it out, the window will have a full screen button and I will be able to shrink it. I have experimented with declaring the variable other places, such as in the struct where I contain the Window and GLXContext.
What is going on here? The way I see it I either have a very subtle and unusual bug coming from my virtual machine or something weird like that, or I have missed some obvious piece of information. Can anyone shed some light on this?
Well, I have no explanation for why declaring a XWindowAttributes instance in main was making it work, but I did figure out what was wrong with my code and I was able to make it behave as expected when I made the following changes:
Do not create XSizeHints directly as shown above. Create it as follows:
XSizeHints *hints = XAllocSizeHints();
Set flags in the object specifying which variables are used:
hints->flags = PMinSize|PMaxSize;
Use XSetWMNormalHints and XSetWMSizeHints:
XSetWMNormalHints(dpy, win, hints);
XSetWMSizeHints(dpy, win, hints, PMinSize|PMaxSize);
I also put a pointer to the hints in my struct containing data about the window. All together the code above became:
XSizeHints *hints = wind->hints = XAllocSizeHints();
hints->flags = PMinSize|PMaxSize;
hints->min_width = hints->max_width = setup.w;
hints->min_height = hints->max_height = setup.h;
XSetWMNormalHints(dpy, win, hints);
XSetWMSizeHints(dpy, win, hints, PMinSize|PMaxSize);
For those that came here:
1. Communicating with the Windows Manager
It's all about convention like said at 12.3 in the "Xlib Programming Manual VOL1". Some WM will completely ignore hints like max & min size, because eg they manage Windows as Tiled Windows. So, how YOUR Window Manager will get your choices is an issue.
2. Make things in the right order.
This will perhaps answer your question : "What is going on here?"
Most difficulties with X comes from the order you make things. I encountered the same trouble as yours, and solve it because I saw I didn't follow the right process.
Chapter 12.3.1 from the "Xlib Prog Manual" says:
'Once the client has created the windows, BUT BEFORE IT MAPS THEM, it must place properties to help WM manage them effectively'
In your case, it means you cannot use XSetWM* functions AFTER your window is mapped. Some properties will have an effect, some others not, and sometimes some will be overridden with bad values.
3. The right order. (AFAIK)
a. Set an Error Handler
b. Get a Display
c. Init your Context (here GLX) & get a Visual from it.
d. set Window Attributes (events mask, ...)
e. Create your Window
e. Set WM Properties (eg your sizehints, min/max size, class, title, ...)
e.1 always init pointers you need with XAlloc* when possible
e.2 use X11r4 XSetWMProperties that will put them all at once, avoid use of deprecated functions.
e.3 XFree your 'pointers'
f. Set the Wm Protocols you are interested in (WM_DELETE_WINDOW, ...)
g. set some others properties according to your needs (eg _NET_WM_PID, ...)
h. Finally, Map your Window
4. See what happens : use xprop
xprop will report how your window is known by your Windows Manager.
If your size hints were properly set, you will see some lines like:
WM_NORMAL_HINTS(WM_SIZE_HINTS):
user specified location: 550, 200
user specified size: 500 by 500
program specified minimum size: 500 by 500
program specified maximum size: 65535 by 65535
Hope it helps future users,
(PS: the previous answer TS#Oct 27 '14 at 15:26 has an error: XSetWMSizeHints expect an Atom as 3rd arg.).

Why might CreatePointFont() return NULL for me?

In my WTL app Im trying to change the font of a static label. But CreatePointFont returns NULL. Why might this be?
CFont font;
font.CreatePointFont(120, _T("Segoe UI"));
text.Attach(GetDlgItem(IDC_MAINTEXT));
text.SetFont(font);
Are you sure that CreatePointFont is returning NULL?
For a font to be set, it must remain in memory, whereas from your code snippet it appears that the variable font is destroyed directly after setting it.
Declare the variable somewhere that will not be deleted during the lifetime of the text object, such as the class if you are using an MFC object.
The nPointSize argument to CreatePointFont() is in tenths of a point, perhaps your size of 12/10 = 1.2 points is too small. You probably meant to pass in 120.
On a lighter note, you may also want to visit the ban comic sans web site, if you're using this for a business application.
The documentation is not too verbose on the fail conditions, but my guess it you don't have the named font on the machine
Check if it is listed by the EnumFontFamilies function (quote form the documentation):
The Windows EnumFontFamilies function can be used to enumerate all currently available fonts