Why does my listview keep drawing in LargeIcon View? - c#

I have a inherited Listview which standard has to be in Tile Mode. When using this control, the DrawItem gives e.bounds which are clearly bounds of largeIcon view ?? When debugging to check the view it is actually set to, it says it's in Tile view ?? Yet e.DrawText draws LargeIcon view ??
......... Edit: .................
This seems only to happen when the control is placed upon another usercontrol?
......... Edit 2: .................
It gets stranger ... When i add buttons next to the list to change the view at runtime, "Tile" is the same as "LargeIcon", and "List" view is the same as "SmallIcons" ??? I've also completely removed the ownerdraw ...
.......... Edit 3: .................
MSDN Documentation:
Tile view
Each item appears as a full-sized icon
with the item label and subitem
information to the right of it. The
subitem information that appears is
specified by the application. This
view is available only on Windows XP
and the Windows Server 2003 family.
On earlier operating systems, this value is ignored and the ListView
control displays in the LargeIcon
view.
Well I am on XP ?!?
...... Edit 4 .....................
Holy mother of strangeness ...
We are now at the point we've completely stripped down EVERYTING ... We have a standard listview on a form, manually filled with 3 values. No Ownerdraw. It is set to Tile.
When we start this form, the list is drawn as LARGEICON.
Now, we start another blank solution, copy this exact same form to the new project, start debug and low and behold .. it is drawn in TILE view ????
... help ...
public class InheritedListView : ListView
{
//Hiding members ... mwuahahahahaha //yeah i was still laughing then
[BrowsableAttribute(false)]
public new View View
{
get { return base.View; }
}
public InheritedListView()
{
base.View = View.Tile;
this.OwnerDraw = true;
base.DrawItem += new DrawListViewItemEventHandler(DualLineGrid_DrawItem);
}
void DualLineGrid_DrawItem(object sender, DrawListViewItemEventArgs e)
{
View v = this.View;
//**when debugging, v is Tile, however e.DrawText() draws in LargeIcon mode,
// e.Bounds also reflects LargeIcon mode ???? **
}
................................
This code behaves differently at different solutions:
private void InitializeComponent()
{
System.Windows.Forms.ListViewItem listViewItem1 = new System.Windows.Forms.ListViewItem("fhsdhdsfhsdfhs");
System.Windows.Forms.ListViewItem listViewItem2 = new System.Windows.Forms.ListViewItem("fdshdsfhdsfhsd");
System.Windows.Forms.ListViewItem listViewItem3 = new System.Windows.Forms.ListViewItem("hdshsdfhsdfhsdfsdfsdf");
this.listView1 = new System.Windows.Forms.ListView();
this.SuspendLayout();
//
// listView1
//
this.listView1.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
listViewItem1,
listViewItem2,
listViewItem3});
this.listView1.Location = new System.Drawing.Point(36, 12);
this.listView1.Name = "listView1";
this.listView1.Size = new System.Drawing.Size(487, 242);
this.listView1.TabIndex = 2;
this.listView1.TileSize = new System.Drawing.Size(480, 50);
this.listView1.UseCompatibleStateImageBehavior = false;
this.listView1.View = System.Windows.Forms.View.Tile;
//
// TestControl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(595, 712);
this.Controls.Add(this.listView1);
this.Name = "TestControl";
this.Text = "TestControl";
this.ResumeLayout(false);
}
#endregion

OK, we found it. The magic spell is:
Application.EnableVisualStyles();
We skipped this line of code to test our form.
If you don't call this method before you create your form with your listview, TILE view gets drawn as LARGEICON.
Seems totally logical ... :-(
http://blogs.msdn.com/rprabhu/archive/2003/09/28/56540.aspx
Q What does Application.EnableVisualStyles actually do?
Windows XP ships with two versions of the Common Controls Library (comctl32.dll) - versions 5.8 and 6.0. v5.8 renders controls in the "Classic" style that you get on Windows NT/2000 and Windows 9x. v6.0 renders controls using the XP Visual Styles look and feel. Since most Windows Forms controls are based on comctl32, how they are rendered depends on which version of comctl32 is used to do the rendering. By default, v5.8 is used to render the client area of the app and v6.0 is used to render the non-client area. That is why you see the title bar and window borders automatically render "themed", while the controls (like Button, TextBox, ListView, ComboBox and so on) have the classic look by default.
In v1.0 of the Framework, the way to get visual styles in a Windows Forms app was to ship a manifest file with the app, that has information in it to indicate that v6.0 of comctl32 should be used for rendering. While this works fine, many developers felt it cumbersome to author, maintain and deploy manifest files. They felt the need to be able to do this programmatically. Now, the Platform SDK does provide API to do this. Basically, you need to create and activate an Activation Context that has pretty much the same DLL redirection information in it as the manifest file. The Activation Context API can be used to do this in a way suitable to your application.
If you take a look at these API, you will probably notice that they aren't very easy to use. While the advanced developers may like to tinker around with activation contexts, it is probably not something a developer who wants some "quick and dirty" code to get visual styles will do. So the Windows Forms team decided to wrap these API and expose a simple method that developers could call, that would isolate them from these complexities. So, essentially, when you call Application.EnableVisualStyles, we set up an activation context around the application's message loop, so that comctl32 function calls can be properly redirected to comctl32 v6.0. That way, you don't need to include a manifest with your app.

Related

Disabling or removing the close button from uwp app

Universal app does not allow to remove or disable the close button it seems. We can hide it by going full screen. But when moving cursor over it, brings title bar back. Is there any way to remove the close button?
Reason : I am working on screen time. After allowed time gets over, I want to block the screen. I should remove close button so that user cant get over my app.
Edit : Removing close button wont help completely. It is a part of work. I am just asking how to remove it.
In Windows 10 version 1703 (build 10.0.15063) and beyond, you can prevent the app from closing, using the SystemNavigationManagerPreview class.
Add this to your app manifest:
<Capabilities>
<rescap:Capability Name="confirmAppClose" />
</Capabilities
You need to have the rescap namespace at the Package element:
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
In the constructor of your main form, add:
var sysNavMgr = SystemNavigationManagerPreview.GetForCurrentView();
sysNavMgr.CloseRequested += OnCloseRequested;
OnCloseRequested can be implemented as follows:
private void OnCloseRequested(object sender, SystemNavigationCloseRequestedPreviewEventArgs e)
{
var deferral = e.GetDeferral();
e.Handled = true;
deferral.Complete();
}
With current released API, we are able to customize the color of these three buttons in title bar. But there is no property or method could be used to disable or remove these buttons.
In UWP, we can use ApplicationView.TitleBar | titleBar property to get the title bar like following:
ApplicationViewTitleBar titleBar = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().TitleBar;
This property's type is ApplicationViewTitleBar. It only has several properties that can customize the button's color like:
titleBar.ButtonBackgroundColor = Windows.UI.Colors.White;
titleBar.ButtonForegroundColor = Windows.UI.Colors.White;
titleBar.ButtonHoverBackgroundColor = Windows.UI.Colors.White;
titleBar.ButtonHoverForegroundColor = Windows.UI.Colors.White;
titleBar.ButtonInactiveBackgroundColor = Windows.UI.Colors.White;
titleBar.ButtonInactiveForegroundColor = Windows.UI.Colors.White;
titleBar.ButtonPressedBackgroundColor = Windows.UI.Colors.White;
titleBar.ButtonPressedForegroundColor = Windows.UI.Colors.White;
Using these properties may make the close button invisible like:
However this won't actually hide these buttons. Users can still minimize or maximize the app and when the pointer is over the top right corner, they will still see the close button.
From Windows 8.1, if we want users to use only an application and do nothing else including closing the application, we can use Kiosk Mode. For more info, please see Enable Kiosk Mode in Windows 8.1 and Set up a kiosk on Windows 10 Pro, Enterprise, or Education. However this won't meet your requirement as you want to block the screen after allowed time gets over.
So UWP may not be the best choice for your requirement. You may try to implement it with classic desktop apps.
in App.Xaml.cs add this code :
// Collapse Title bar
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
Window.Current.SetTitleBar(null);
ApplicationView view = ApplicationView.GetForCurrentView();
view.TryEnterFullScreenMode();
C++ Version
// COLLAPSE THE TITLE BAR
Windows::ApplicationModel::Core::CoreApplication::GetCurrentView()->TitleBar->ExtendViewIntoTitleBar = true;
Window::Current->SetTitleBar(nullptr);
Windows::UI::ViewManagement::ApplicationView^ view = Windows::UI::ViewManagement::ApplicationView::GetForCurrentView();
view->TryEnterFullScreenMode();

C# dynamic update of control created in a dll

I created a Control and compiled it into a DLL:
namespace TSControlLibrary
{
public partial class BaseMaskedTextBox : MaskedTextBox
{
public BaseMaskedTextBox()
{
InitializeComponent();
this.BackColor = Color.Pink;
}
}
}
Then I created another Test project and want to use this new MaskedTextBox on it...
Which pretty much works,
1 - I added the reference to the DLL in Test. And kept the default properties. Copy Local = True, Specific Version = False
2 - I added the DLL to the toolbox, which shows the BaseMaskedTextBox.
Now I can add a new masked thingy onto my winform. :-)
BUT!!! But when I want to change the original DLL from Color.Pink to Color.Blue it will allow me to add a new MaskedTextBox on the form in Blue. But the Pink is still Pink.
What I would like to do is change the DLL color, recompile that and the new Test project will have the new color. How can I do this?
VS2012, winforms, heh.
hmm... well, it looks like I figured it out. :-)
I found that the DLL color set works, it updates the color from the default to Green or whatever, but then the Test.Designer.cs runs after that and just resets it to whatever it was when I added it hours ago.
So after a while on my Test form I have 30 different boxes all different colors. Because the designer.cs keeps track of where they go and some other things - like colors and font size and things.
So, I found that LocationChanged event will fire after the designer, but before it shows on the screen. So that was the ticket.
public BaseMaskedTextBoxDate2()
{
this.LocationChanged += new EventHandler(Setup);
}
//*************************************************************************************************
private void Setup(object sender, EventArgs e)
{
MaskedTextBox maskedBox = (MaskedTextBox)sender;
maskedBox.BackColor = Color.Gray; // For testing and also to make sure all fields are handled.
maskedBox.Font = new Font("Microsoft Sans Serif", 10.0f);
maskedBox.ValidatingType = typeof(System.DateTime);
maskedBox.BeepOnError = false;
maskedBox.TypeValidationCompleted += new TypeValidationEventHandler(maskedTextBoxDate_TypeValidationCompleted);
...
}
Now, if I have the DLL version ( above ) open in an instance of VS and make a change, say to the font size, going from 10 to 20, on the other instance of VS that is Test it will update on the Test Design View instantly - and with 20 font it will also be pretty nasty looking... And when compiled it will also be correct - as shown in Design.
Oddly, the only thing that I can't change is the Mask. But I doubt I will ever change that from 00/00/0000 - at least for this project anyway.

Windows Phone navigation buttons overlap with screen resolution

below you'll see a screen running in Windows Phone 8.1 one 2 devices. Both are claiming to have Viewport Width and Height of 800x480 however as you can see from the image the 635's nav buttons are overlapping the game area.
I have checked various properties in GraphicsDevice.Adapter and GraphicsDevice.Viewport, but they are both the same!
The screen is running within C# UWP Monogame code. I set the PrefferedBackBufferWidth and Height to 480x800.
How can you tell if the nav buttons with take up part of the screen?
I will expand the answer further.
In windows phone 8.1, you have two ApplicationViewBoundsMode enum values.
UseVisible, pages inside application will use only the visible area excluding StatusBar, application bar and Soft navigation buttons.
To make your app use ApplicationViewBoundsMode.UseVisible option, add the following in app.xaml.cs before `Windows.Current.Activate();
#if WINDOWS_PHONE_APP
ApplicationView.GetForCurrentView().SetDesiredBoundsMode(ApplicationViewBoundsMode.UseVisible);
#endif
UseCoreWindow, lay out the window's content within the region occupied by the core window (that is, including any occluded areas- including soft navigation buttons).
To make your app use ApplicationViewBoundsMode.UseCoreWindow option, add the following in app.xaml.cs before Windows.Current.Activate();
#if WINDOWS_PHONE_APP
ApplicationView.GetForCurrentView().SetDesiredBoundsMode(ApplicationViewBoundsMode.UseCoreWindow);
#endif
In some cases, developers may want to use UserCoreWindow option to show content under app bar but as a side effect navigation soft buttons will occlude parts of your page to resolve it, follow the next solution.
You can listen for ApplicationView.GetForCurrentView().VisibleBoundsChanged in WindowsPhone and update the margin of your page.
Here is an article written by Joost van on fixing this issue (and a behavior that you can use out of the box)
Quoting the issue explanation from the above link
If the application view bound mode is set to ApplicationViewBoundsMode.UseCoreWindow in App.Xaml.cs the phone reports the whole screen size – not only the part that is normally taken by the status bar on top and the application bar at the bottom, but also the part that is used by the button bar.
And a snippet from his solution where he updates the margin of page
void KeepInViewBehaviorVisibleBoundsChanged(ApplicationView sender, object args)
{
UpdateBottomMargin();
}
private void UpdateBottomMargin()
{
if (WindowHeight > 0.01)
{
var currentMargins = AssociatedObject.Margin;
var newMargin = new Thickness(
currentMargins.Left, currentMargins.Top, currentMargins.Right,
originalBottomMargin +
(WindowHeight - ApplicationView.GetForCurrentView().VisibleBounds.Bottom));
AssociatedObject.Margin = newMargin;
}
}
to hide the navigation bar in your monogame windows phone 8.1 game add the following code in your app.xaml.cs file under InitializePhoneApplication() method
RootFrame = new PhoneApplicationFrame();
//I have set it to RootVisual to hide navigationbar
RootFrame.FullScreen = true;
if (RootVisual != RootFrame)
RootVisual = RootFrame;

Docking an existing QWidget in QWindow

For those who are very familiar with C# or VB.NET using the UserControl component in the .NET Framework (which is the hottest framework in my opinion), you were used to adding several buttons that preview different user controls as follows:
1) First you would prepare an appropriate user interface (contains 3 buttons and a single panel on the right area to view each user control after clicking one of the added buttons).
2) Adding 3 user controls from the solution explorer...
3) Inserting the content on each user control...
4) Implementing code for the 3 buttons on the frmMain.cs as the following (for this implementation we will be implementing the "Welcome" button carrying the object name as welcomeBtn, and the rest will have identical code but different user control names instead):
private void welcomeBtn_Click(object sender, EventArgs e)
{
//Clear up everything from the panel if any item exist(s)...
mainPanel.Controls.Clear();
//Create a new instance of a user control for the button...
UserControl1_Welcome welcome = new UserControl1_Welcome();
//Show up the created instance of the user control
mainPanel.Controls.Add(welcome);
}
5) Finally, the program will end up initially like this when running:
http://i.stack.imgur.com/OENwG.png
** Usage of the program **
When you click on the "Welcome" button for example, the result should be expected to be like this:
http://i.stack.imgur.com/iCyo3.png
... and when you click on a different button, lets say "License Agreement" button, you would expect to see something other than your current selection.
MAIN QUESTION
How can we bring the simplicity of Windows Forms in QT CREATOR by applying the "QDockWidget"?
I have tried inserting the QDockWidget component with no problems, but when I try to do the equivalent .NET code for adding the QWidget inside the QDockWidget:
ui->dockWidget->setWidget(myWidget);
which I think is equivalent to this line of code in C#.NET (correct me if I'm wrong here):
ui.Controls.Add(myWidget);
After using this code, my program won't crash nor shows anything running...
P.S. I'm sorry for linking the images, I don't have 10 reputation for making them show up...
What I want is to have a program that does the same thing with the C# example (showing a user control based on the click of a button).
If you want to show a particular widget based on a button click, I suggest to use a QStackedWidget
A simple example would be like this:
// In the constructor of your CustomWidget
// Create your buttons
QPushButton* firstButton = new QPushButton("First Button", this);
QPushButton* secondButton = new QPushButton("Second Button", this);
QPushButton* thirdButton = new QPushButton("Third Button", this);
// Create your (custom) widgets
QLabel* firstPageWidget = new QLabel("First Label", this);
QLabel* secondPageWidget = new QLabel("Second Label", this);
QLabel* thirdPageWidget = new QLabel("Third Label", this);
// Add them to the stackWidget
/*QStackedWidget* */ m_stackedWidget = new QStackedWidget(this);
m_stackedWidget->addWidget(firstPageWidget);
m_stackedWidget->addWidget(secondPageWidget);
m_stackedWidget->addWidget(thirdPageWidget);
// Insert buttons and stackWidget to CustomWidget
QVBoxLayout* layoutStack = new QVBoxLayout();
layoutStack->addWidget(m_stackedWidget);
QVBoxLayout* layoutButtons = new QVBoxLayout();
layoutButtons->addWidget(firstButton);
layoutButtons->addWidget(secondButton);
layoutButtons->addWidget(thirdButton);
QHBoxLayout* layout = new QHBoxLayout();
layout->addLayout(layoutButtons);
layout->addLayout(layoutStack);
setLayout(layout);
// Connect button clicks to slots
connect(firstButton, SIGNAL(clicked()), this, SLOT(onFirstButtonClicked()));
connect(secondButton, SIGNAL(clicked()), this, SLOT(onSecondButtonClicked()));
connect(thirdButton, SIGNAL(clicked()), this, SLOT(onThirdButtonClicked()));
Then you change the currently visible widget in the slots:
void CustomWidget::onFirstButtonClicked() {
m_stackedWidget->setCurrentIndex(0);
}
void CustomWidget::onSecondButtonClicked() {
m_stackedWidget->setCurrentIndex(1);
}
void CustomWidget::onThirdButtonClicked() {
m_stackedWidget->setCurrentIndex(2);
}
Note that if you want the button clicks just to simply change some text (as opposed to change the visible widget), you probably better use a QTextEdit instead of a QStackedWidget, and in the slots call setText("....");
If you have a lot of buttons, you'd better use QSignalMapper to limit the number of slots.
Also, I didn't get why you mentioned QDockWidget since they have a quite specific usage:
The QDockWidget class provides a widget that can be docked inside a QMainWindow or floated as a top-level window on the desktop.
QDockWidget provides the concept of dock widgets, also know as tool palettes or utility windows. Dock windows are secondary windows placed in the dock widget area around the central widget in a QMainWindow.
If you simply want a separate window, you're probably looking for a QDialog
How to do this with QtDesigner:
First you would prepare an appropriate user interface (contains 3 buttons and a single QStackedWidget on the right area to view each user control after clicking one of the added buttons).
Adding 3 pages for the user controls in the stack (+ one for the "empty" page if you really need that). If you want to design the Controls in separate UI Files / Only in Code (instead of all controls in your MainFrame), you would add plain QWidgets and promote them to the appropriate specific widget type
Inserting the content on each user control...
Implementing code for the 3 buttons on the frmMain.cpp/.h as the following (for this implementation we will be implementing the "Welcome" button carrying the object name as welcomeBtn, and the rest will have identical code but different user control names instead):
void FrmMain::on_welcomeBtn_clicked() {
ui->stack->setCurrentWidget(ui->welcomeWidget);
}
Select the "empty" page at as the current page in the designer, so the program will end up initially like this when running: (your screenshot)
When you click on the "Welcome" button for example, the result should be expected to be like this: (your second screenshot)
In my opinion, Miki's answer is the only correct approach to this use case (using a QStackedWidget).
For sake of completeness, I'll demonstrate how the same Clear and Add method as used in .NET is done in Qt:
// Assume controlPanel is a QWidget where you want to place the items
// Assume that controlPanel has set a layout (e.g. QHBoxLayout)
// Clear: Remove all Items from layout
QLayoutItem *child;
while ((child = controlPanel->layout()->takeAt(0)) != NULL) {
delete child;
}
// Now widgets are still there, but not layouted. Delete them explicitly
foreach (QWidget * w, controlPanel->findChildren<QWidget*>()) {
w->deleteLater();
}
// Now controlPanel is cleared
// Add new control
controlPanel->layout()->addWidget(new MyNewControlWidget);
First is, we can not force how other framework works to another one. Each framework has its flow and design.
What I am understand is you want to show another widget to the main window.
If you want to use the QDockWidget, its says on the documentation like this :
void QDockWidget::setWidget(QWidget * widget)
Sets the widget for the dock widget to widget.
If the dock widget is visible when widget is added, you must show() it explicitly.
Note that you must add the layout of the widget before you call this function; if not, the widget will not be visible.
Please share here you code of myWidget, so we can try to help you to figure out what is wrong.
On my side, I can achieve it by add the QVboxLayout on your ui->dockwidget and add QLabel with emtpy string and when you want to show myWidget just call ui->dockwidget->vboxlayout->replaceWidget(label, myWidget);

How to subsequently add scaling behaviour in a WinForms application?

I am working on a WinForms application using Visual Studio 2008 (C#). The user interface of the concerning form consists of several SplitContainers.
When I tested the application after setting the Windows font size to 125%, the form didn't look any more as it should. There obviously was a problem with scaling. Therefore I've searched for a solution and found one here. The two following lines did the job for me:
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
As explained in the other question (in one of the answers, respectively), they have to be included for every container in the designer file. It works and scaling performs correctly. But on the other hand, I have to manually edit the designer file and that's something one actually shouldn't do. The added lines get lost every time I use the layout designer.
EDIT: Just to clarify: These two properties are not shown in the designer gui.
Now finally, my question is: What can I do? How or where can I add the code for correct scaling without dirty manipulation of the designer file?
I have already tried to simply put these two lines for every container in the constructor after the InitializeComponent() method call, but at this position, they don't have the desired effect.
So, maybe you have an idea how it has to be done.
Thanks in advance,
Alex
I've finally found a way to solve the problem. It isn't really what I intended originally, but it has the same effect.
The concerning two properties don't show in the designer gui, so why not make them appear? Therefore I created a custom control and added some attributes to both scaling properties, so that they appear in the designer.
public class ScalableSplitContainer : SplitContainer
{
[Browsable(true)]
[EditorBrowsable(EditorBrowsableState.Always)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Bindable(true)]
public new AutoScaleMode AutoScaleMode
{
get { return base.AutoScaleMode; }
set { base.AutoScaleMode = value; }
}
[Browsable(true)]
[EditorBrowsable(EditorBrowsableState.Always)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Bindable(true)]
public new SizeF AutoScaleDimensions
{
get { return base.AutoScaleDimensions; }
set { base.AutoScaleDimensions = value; }
}
}
Using this specialized SplitContainer, scaling behaviour can easily be set in the gui and the code lines are included in the generated designer file.

Categories

Resources