How to highlight header column on mouse hover? - winapi

I have an owner drawn header of a ListView control. If the header is not owner drawn we have a nice hover effect when mouse is on one of the header's columns. After I made header columns owner drawn I have to take care of the hover effect myself.
In order to catch it I monitor WM_MOUSEMOVE message within header window and when I get this message I redraw the column of a header with changed background first and on top of that I draw text and other necessary graphics. There is just one but... The font of a text becomes bold.
You can see it below. First header is mine, and second header is from Windows explorer with hover effect on Date modified column.
Why does the font suddenly becomes bold?
Is this the right way to implement hover effect? Maybe I missed some Header specific notification?

In owner draw mode you have to take care of everything including fonts. Don't assume you know what the current DC font is. If you want a specific font you need to select one into the DC before drawing text.

Well, I solved this mystery :) Even though I still don't know why the font used in DrawThemeText function suddenly changed in WM_MOUSEMOVE notification. My approach still relies on catching WM_MOUSEMOVE event and redrawing the column underneath the mouse pointer. In order not to change the default header font (like in illustration in my question) I used the following code to get and set it:
HFONT displayFont = (HFONT)SendMessage( header, WM_GETFONT, 0, 0 ); // gets default header font
SelectObject(hdc, displayFont); // sets device context to use newly found font
This solution has at least one drawback: I redraw the Header too frequently (each time mouse moves within header column).

Related

How can I make a UITextField with padding on the left of the content?

UITextField shows its content text bang against the left edge of the field, which is ugly and can be hard to read if the field has a visible border. UITextView, on the other hand, automatically has padding (blank space) around the text. I examined and experimented with all the UITextField properties but I don't see any way they can be used to get padding around the text.
I also tried calling drawText(in:CGRect) on the text field but it had no effect. But I'm not sure what CGRect is needed in that call. I tried different border styles including .none. I also tried making a blank UIView and assigning that to the text field's leftView property but that also had no effect. And I tried doing these things in viewDidLoad, viewDidAppear, and at the point where I'm writing the text into the textField. The text shows in the textField as expected but none of these other things seem to affect the textField's appearance in any way. It seems to me lots of people must show text in a UITextField and somehow get it padded on the left so I'm misunderstanding something but what???
The following works for a field called "textField". It inserts padding by shifting the left side of the field's content 8 pixels right relative to the left edge of the textField:
textField.layer.sublayerTransform = CATransform3DMakeTranslation(8, 0, 0);
This is given in an answer to a different question by user Dhiru (reputation 1285) in Nov. 2016. Thank you Dhiru!
I have to add that I am not familiar with either sublayerTransform or CATransform3DMakeTranslation so I can't be sure that this doesn't have some side effect that isn't immediately obvious. I'm a little worried that it's called "3D transform" whereas there is nothing 3D about my application. But at least for now this seems to answer the question.

Why is the width of my SupplementaryView for a section Header wrong in this UICollectionView?

I am making a booking system in my iPad app that uses sections for days and cells for bookings. New bookings can be added by clicking the button on each day section.
As you can see in the image, I have 24 pixels of space on each side of my cells. These are brought in from a separate xib file into the screen's xib. I also bring the section's supplementary view in this way, however, I can't achieve the same effect. One thing to note is that I have a CollectionViewReusableCell on the parent screen. I'm not sure if this makes a difference.
Things I have tried
I've tried putting a view inside of the header's xib which instead would have the desired width, and have set the superview's background colour to transparent, as advised here. I couldn't get the leading or trailing space to work with auto layout though.
I've also tried setting the section insets of the collection view to 24 pixels on the left and right as detailed here. I've tried this on the designer and from code by setting EdgeInsets on the flow layout. But this still does not work.
What am I doing wrong (or right) here?
Fixed my issue, using this line of code in ViewDidLoadof the ViewController.
View.CollectionView.ContentInset = new UIEdgeInsets(0, 24, 0, 24);
That sets the section padding for the left and right to 24 pixels.

Treeview control in Win32 API - how to display a single treeview item using different fonts?

I'm faced with a problem where I need to display some characters in a tree-view item (those belonging to the Symbol charset) using Symbol font while others in the default System font (Segoi UI on my Windows 7).
Custom draw allows us to draw different items using different fonts, but I would like to draw the same item string using different fonts as it applies to each character in the string as told above.
So, what I've done with not-so-pleasing results w.r.t. drawing performance upon a horizontal scroll when the number of items is more so far is this:
I disabled horizontal scrolling in my tree-view control using TVS_NOHSCROLL style (since I'm using my own scroll bar control inside the tree-view window to handle all horizontal scrolling)
I sub-classed the treeview control and in the sub-classed winproc, I handle the horizontal scroll notification and mouse notification (where I do my own hittesting and send message like TVM_EXPAND and TVM_SELECT as a result of mosue clicks/double-clicks). Also the scroll bar range is set based on how wide my custom drawn string is (the maximum length amongst all items).
I draw the string for each item upon receiving CDDS_ITEMPOSTPAINT using my own fonts for each character in the item.
The above approach (I left out some details for the sake of brevity) works BUT there are some problems which makes me post this question here and look for an alternare way:
Problems:
The horizontal scroll bar control I create is hosted "inside" the tree-view control at the bottom of the tree-view window. However, when the number of items goes beyond what the tree-view client area can accommodate vertically, the last visible tree-view item gets obscured by the scroll bar control. This can be solved by not making the scroll bar a child of the tree-view and hosting it outside the tree-view window just below it. But I don't want to do this since the scroll bar should typically be a child window of the tree-view.
This is the major one. Since I draw the items myself at each horizontal scroll, the drawing performance upon horizontal scrolling is very slow and also leads to flicker upon scrolling.
Any ideas will be much appreciated as I've been grappling with this for the last one week without success.
I can also post the relevant code here if you want to see the approach I took but I'm sure there shoould be a better approach to this and there must be some other people who would've faced this problem and solved it in the past.
Thanks in advance.
Custom-draw allows you to draw items however you want. You are not limited to a single font per item. When you receive the NM_CUSTOMDRAW notification, draw whatever you want on the provided HDC for the specified item. You can draw pieces of text in one font, pieces of text in a different font, etc. Be sure to return CDRF_SKIPDEFAULT so the TreeView itself will not try to draw anything on the item.
#Anurag S Sharma: I tried to edit this into Remy's answer. It's incomplete as is, but addresses your comment/concerns and answers this particularly vexing/useful question...
The problem is that ff I return CDRF_SKIPDEFAULT, Windows does not even draw the +/- buttons (expanding/collapsing) nor the indent lines in the control which I do want Windows to draw. – Anurag S Sharma
To retain the lines, buttons, and icons you can use ExcludeClipRect to mask only the text region and instead of returning CDRF_SKIPDEFAULT, return 0 as if you didn't draw anything. This itself would not be necessary if the text of the tree item was empty, except that the margins of the text will always be drawn by the default handler (note that Microsoft's controls do not always respect clipping shapes, but in this case they do.)
To replicate the classic TreeView label style in your custom draw procedure you need to do something like the following:
HTREEITEM item = (HTREEITEM)p->dwItemSpec;
TreeView_GetItemRect(p->hdr.hwndFrom,item,&p->rc,1);
RECT cr, rc = p->rc; GetClientRect(p->hdr.hwndFrom,&cr);
DrawTextW(p->hdc,text,-1,&rc,DT_CALCRECT|DT_NOPREFIX|DT_NOCLIP);
rc.right+=4; rc.bottom+=2; IntersectRect(&rc,&cr,&rc);
ExtTextOutW(p->hdc,rc.left+2,rc.top+1,ETO_CLIPPED|ETO_OPAQUE,&rc,text,wcslen(text),0);

NSWindow and text smoothing in NSTableView cell view

I'm writing an OS X app and have a problem with font smoothing in separate window.
I have a text field where you put text and suggestion window which pops up with a list of suggestions according to what you wrote. I'm using View-cell based NSTableView to display those suggestions and SFBPopoverWindowController to display it as a "popup" window (tried other classes with the same effect). When rows are first drawn they look fine but after I select them (keyboard or mouse) the font changes it's weight. It's only visual - like you would change smoothing method on the font, not it's bold setting.
"Music note" is the selected cell here
What's even more strange is that after I hide and show the window 3 times everything works fine from that point on.
Again - "Music note" is the selected cell.
The selection is done by overwriting NSTableRowView class and its drawSelectionInRect: method but I tried with drawing everything inside custom NSTableCellView class and it didn't help. The text is standard NSTextField - nothing's changed there.
The SFBPopoverWindow (and it's controller) are created once and reused with styleMask NSBorderlessWindowMask, backing NSBackingStoreBuffered, defer set to YES. The only change in SFBPopoverWindowController I made was to turn off window becoming key window but it doesn't change anything.
It might be related to the way a table view draws it's selected cells (setSelectionHightLightStyle:). Try to set the style to None/ NSTableViewSelectionHighlightStyleNone in your code or IB / Storyboard-file and draw the selection yourself (in a NSTableRowView subclass).
Background: When you use NSTableViewSelectionHighlightStyleRegular or NSTableViewSelectionHighlightStyleSourceList the table view assumes that you use the standard selection behaviour and appearance and does some magic to support that.
==========
UPDATE
==========
My previous answer is still valid but since it only describes the problem and hints at a workaround, I wanted to add a real solution. If you want to use NSTableViewSelectionHighlightStyleRegular for your table view (with custom font and colors), you need a way to 'disable' the system magic that comes into place once your row is highlighted. One proposed solution is to decline the first responder status. It has a lot of drawbacks and isn't a good solution at all.
So, let's have a closer look at the system 'magic' that kicks in as soon as the row will be highlighted: NSTableRowView has a property interiorBackgroundStyle that is – according to the documentation – 'an indication of how the subviews should draw'. Furthermore 'This value is dynamically computed based on the set of properties set for the NSTableRowView. Subclassers can override this value when they draw differently based on the currently displayed properties. This method can also be called to determine what color a subview should use, or alternatively, NSControls can have the -backgroundStyle set on their cell to this value.'
I assume that this style will be handed down the subview hierarchy and causes your text fields to look odd. The system assumes that a highlighted cell has a dark background and changes the interiorBackgroundStyle to dark. Other controls try to adapt accordingly.
I think there are two solutions to this problem:
1) Override interiorBackgroundStyle in your NSTableRowView subclass and return the style that fits your interface (in my case it's .light because my highlight color is a very bright blue). This worked for me.
2) If changing the whole style is a bit too much because you only want certain elements to not change their style, you may only need to adjust these subclasses. I haven't tried this yet.

NSTextView lineHeightMultiple drawing issues

By setting the lineHeightMultiple of a NSParagraphStyle that is used in a text view I'm getting drawing artifacts when selecting text. This is reproducible in TextEdit. More specifically:
Open TextEdit in rich text mode
Pick Courier 14 as the font
Set line height multiple to 1.4
Insert a bunch of text
Select a portion of text with the mouse until the top
Start decreasing the selection (moving the mouse down)
In some lines, the selection is not totally cleared, leaving a 1px horizontal artifact behind (see screnshot). This also occurs with different fonts, font sizes as lineHeightMultiple values (although not all).
Has anyone experience this or has any idea why this is happening?
Thanks,
Rúben
I fixed this in my own code by adding the paragraph style to the selected text attributes, and rounding the line height.
I had a similar issue with NSTextAttachment's which were having a height larger than the default line spacing. I was able to mitigate it by adding this line to my NSTextViewDelegate.
func textViewDidChangeSelection(_ notification: Notification) {
// will fix artifacts after releasing mouse button
self.textView.needsDisplay = true
}
I also tried to create a larger redraw area during mouseDragged in my custom NSTextView class, but unfortunately NSTextView is handling this completely different, thus mouseDragged is never being invoked.
The trick with the paragraph style did not work for me.

Resources