I am using the built-in search scope with a UISearchDisplayController, and I only have 2 segments.
The problem is that our design needs the buttons to be smaller and centered (it especially looks bad on iPad because the buttons are stretched really wide).
Is there a way to center the UISegmentedControl and make it smaller? I already have the UISegmentedControl pulled out by looping over subViews. And I can set the width of each segment with setWidth:forSegmentAtIndex, but the control is docked to the left. How can I center it?
PS - my app is MonoTouch (Xamarin.iOS), but Obj-C answers are welcome.
Are you adding this via IB or programmatically? In IB, I had to turn off "Autoresize Subviews" and do the resizing of the control dynamically via code. I put the controls I needed to resize into a view that I could bind to then center my control within that view. Here's a sample. I had 2 buttons that I put side-by-side in landscape mode, but it should give you an idea.
// get the current sizes of the things we are moving
CGRect saveRect = self.viewButtons.frame; // the enclosing view
CGRect addLocRect = self.buttonAddLocation.frame; // button 1
CGRect connectRect = self.buttonConnect.frame; // button 2
// This will be set below in one of the if-else branches
CGFloat buttonWidth = 0;
// determine the offset from the left/right based on device and orientation
int offsetLeft = 0;
int offsetRight = 0;
if ([self isIphone]) {
offsetLeft = (UIDeviceOrientationIsPortrait(toInterfaceOrientation)) ? OFFSET_LEFT_PORTRAIT_IPHONE : OFFSET_LEFT_LANDSCAPE_IPHONE;
offsetRight = (UIDeviceOrientationIsPortrait(toInterfaceOrientation)) ? OFFSET_RIGHT_PORTRAIT_IPHONE : OFFSET_RIGHT_LANDSCAPE_IPHONE;
} else {
offsetLeft = (UIDeviceOrientationIsPortrait(toInterfaceOrientation)) ? OFFSET_LEFT_PORTRAIT_IPAD : OFFSET_LEFT_LANDSCAPE_IPAD;
offsetRight = offsetLeft;
}
// change the size & location of the buttons to maximize the area for the location list
// no matter what orientation, the button frame will fill the bottom of the screen
saveRect.size.width = _windowWidth -offsetLeft - offsetRight;
// for Landscape, move the buttons to side-by-side at the bottom of the window
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
// size & move the buttons to fit side-by-side
buttonWidth = (saveRect.size.width)*.4;
// addLocRect.origin.x += offset;
addLocRect.origin.y = saveRect.size.height - addLocRect.size.height ;
connectRect.origin.x = saveRect.size.width - buttonWidth - offsetRight;
connectRect.origin.y = saveRect.size.height - connectRect.size.height;
} else { // Portrait
// move the buttons down to the bottom of the frame, stacked
// size the buttons to be fully across the screen
buttonWidth = saveRect.size.width-2*offsetLeft;
addLocRect.origin.y = 0 ; // at the top of the button view
addLocRect.origin.x = offsetLeft;
connectRect.origin.y = saveRect.size.height - connectRect.size.height;
connectRect.origin.x = offsetLeft;
}
connectRect.size.width = buttonWidth;
addLocRect.size.width = buttonWidth;
self.buttonAddLocation.frame = addLocRect;
self.buttonConnect.frame = connectRect;
Related
There are some methods from the Screen class to retrieve the respective screen, which contains the most area of a control.
They are the:
Screen.FromRectangle(Rectangle rect)
Screen.FromControl(Control control)
Screen.FromHandle(IntPtr hwnd)
Screen.FromPoint(Point point)
The issue here is that I have a problem getting my second Form to be opened in the second monitor. It kept on displaying only on the primary screen. According to the answer from here, the suspect is that the DpiAware was not enabled. However, the problem was still not fixed even after I have enabled the DpiAware.
To help me to check what was going on, I've added code for debugging. Then, I called/ opened the popup menu on \\\\.\\DISPLAY2. Inside of the debug console, the chosen Screen for FromPoint() was written \\\\.\\DISPLAY2. However, the popup menu was still opened on \\\\.\\DISPLAY1. Can anyone help me with this issue, please?
Below are the codes example:
Under main form class:
//mouseup event handler
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
//if RMB clicked
if(e.Button == MouseButtons.Right)
{
//----set PopupMenu form location----
popupMenuObj.Location = popupMenuObj.popupMenuLocation((sender as Control).PointToScreen(e.Location));
//----set PopupMenu form location----
//process the form location
popupMenuObj.Location = popupMenuObj.processFormLocation(popupMenuObj.Location);
//----set PopupMenu cursor location----
Cursor.Position = popupMenuObj.middleOfPopupMenu(popupMenuObj.Location);
//----set PopupMenu cursor location----
//----display the popup menu----
popupMenuObj.displayPopupMenu(1);
//----display the popup menu----
}
}
Under popup menu class:
//to set cursor to middle of popup menu
public Point middleOfPopupMenu(Point mousePoint)
{
int theCenterWidth = this.Width / 2;
int theCenterHeight = this.Height / 2;
//set the mouse pointer location at middle of PopupMenu
mousePoint.X += theCenterWidth;
mousePoint.Y += theCenterHeight;
return Cursor.Position = mousePoint;
}
//to set popupmenu location
public Point popupMenuLocation(Point thePoint)
{
return this.Location = thePoint;
}
//set popup menu display status
public bool displayPopupMenu(int displayFlag)
{
switch(displayFlag)
{
case 1: //if argument 1 -> display the PopupMenu
this.Visible = true;
return true;
case 0: //if argument 0 -> close the PopupMenu
this.Visible = false;
return false;
default: //by default, no need to display
return false;
}
}
//to process if popupmenu opens exceeding the screen working area
public Point processFormLocation(Point currentPoint)
{
Point newPoint = new Point();
int selectedScrWidth, selectedScrHeight; //screen dimension of the selected screen
Screen selectedScreen;
int totalXPos, totalYPos; //where the form is located before exceed screen is handled
//---get screen where point is at---
selectedScreen = Screen.FromPoint(currentPoint);
Console.WriteLine("\nSelected screen info: {0}\n", selectedScreen); //for debugging purposes
//---get screen where point is at---
//---get selected screen dimension---
selectedScrWidth = selectedScreen.WorkingArea.Width;
selectedScrHeight = selectedScreen.WorkingArea.Height;
//---get selected screen dimension---
totalXPos = currentPoint.X + this.Width; //mouseXCoor + popupMenu width
totalYPos = currentPoint.Y + this.Height; //mouseXCoor + popupMenu height
//if exceed selected screen width and height
if ((totalXPos >= selectedScrWidth) && (totalYPos >= selectedScrHeight))
{
newPoint.X = selectedScrWidth - this.Width;
newPoint.Y = selectedScrHeight - this.Height;
}
//if exceed selected screen width
else if ((totalXPos >= selectedScrWidth))
{
newPoint.X = selectedScrWidth - this.Width;
newPoint.Y = currentPoint.Y;
}
//if exceed selected screen height
else if ((totalYPos >= selectedScrHeight))
{
newPoint.X = newPoint.X;
newPoint.Y = selectedScrHeight - this.Height;
}
else //if x exceed screen, just set the location as is
{
return this.Location = Cursor.Position;
}
return this.Location = newPoint;
}
Update 1:
As per Jimi's request under the comment section, after creating a simple test project based on given answer here, here's what I got:
Please note the reason why the code in the question from the previous thread has no Width, Height, and StartPosition = FormStartPosition.Manual defined was because the popup menu is from a class on another .cs file where, those specific properties have already been declared in the PopupMenu.Designer.cs file. Therefore, I don't feel like redefining was necessary.
Update 2:
Now that it works, a newer problem arises is that, only when popup menu exceeds right boundary of secondary display, the popup menu was displayed on primary screen. However this didn't occur when I try to open the popup menu when exceeding the height of secondary screen. Example is shown below:
Above is the case when I try to open the popup menu when exceeding the width of secondary screen. The popup menu opens at the right boundary of primary screen.
It however worked just fine when I tried the case for exceeding the height of secondary display.
If the MainWindow is too close to the edge of the screen, opening a New Window with relative positioning can go off screen.
I'd like to have it detect that it's off screen and reposition itself close to the edge, even overlapping the MainWindow. For Top, Bottom, Left and Right.
Example Project Source
https://www.dropbox.com/s/3r2guvssiakcz6f/WindowReposition.zip?dl=0
private Boolean IsWindowOpened = false;
// Info Button
//
private void buttonInfo_Click(object sender, RoutedEventArgs e)
{
MainWindow mainwindow = this;
// Start Info Window
InfoWindow info = new InfoWindow(mainwindow);
// Only Allow 1 Window Instance
if (IsWindowOpened) return;
info.ContentRendered += delegate { IsWindowOpened = true; };
info.Closed += delegate { IsWindowOpened = false; };
// Position Relative to MainWindow
info.Left = mainwindow.Left - 270;
info.Top = mainwindow.Top + 0;
// Open Info Window
info.Show();
}
Example of 1280x720 screen
MainWindow Center Screen
InfoWindow -270px Left, 0px Top
Off Screen
MainWindow Top Left of Screen
InfoWindow -270px Left, 0px Top
Reposition In Screen
MainWindow Top Left of Screen
InfoWindow -160px Left, 0px Top
To Place Dialog to Left
The quick-n-dirty way of doing this is to simply use Math.Max (i.e. the right-most value) to use the offset or 0, whichever is larger. Using System.Windows.Forms.Screen allows us to accommodate for multiple monitors.
private void btnInfoToLeft_Click(object sender, RoutedEventArgs e)
{
// Figure out which screen we're on
var allScreens = Screen.AllScreens.ToList();
var thisScreen = allScreens.SingleOrDefault(s => this.Left >= s.WorkingArea.Left && this.Left < s.WorkingArea.Right);
// Place dialog to left of window, but not past screen border
InfoWindow info= new InfoWindow();
info.Left = Math.Max(this.Left - info.Width - 10, thisScreen.WorkingArea.Left);
info.Top = Math.Max(this.Top - info.Height - 10, thisScreen.WorkingArea.Top);
info.Show();
}
Note that we use the Width of the dialog - it's ActualWidth will be 0 before it is shown on the screen.
To Place Dialog to Right
Similarly, we need to figure out the right-most boundaries of the screen, and account for the width of the main window and dialog, and take the Math.Min value (i.e. the left-most value).
private void btnInfoToRight_Click(object sender, RoutedEventArgs e)
{
// Figure out which screen we're on
var allScreens = Screen.AllScreens.ToList();
var thisScreen = allScreens.SingleOrDefault(s => this.Left >= s.WorkingArea.Left && this.Left < s.WorkingArea.Right);
// Place dialog to right of window, but not past screen border
InfoWindow info = new InfoWindow();
info.Left = Math.Min(this.Left + this.ActualWidth + 10, thisScreen.WorkingArea.Right - info.Width);
info.Top = Math.Min(this.Top + this.ActualHeight + 10, thisScreen.WorkingArea.Bottom - info.Height);
info.Show();
}
This time, we still use the Width of the dialog, but the ActualWidth of the main window, which will be the width after it has been drawn (and possibly resized).
In these examples, I've also placed the dialog above/below the main window. You can set the top of the dialog to be equal to the top of the main window, or play around to get it to line up with the bottom, etc., using this example as a guide.
There are no shortcuts for this kind of problem. You'll have to figure out the dimensions of the screen you're using, then adjust the position of the info window manually.
Take a look at this StackOverflow post: How to get the size of the current screen in WPF?
I have been trying for a while to find the exact location of a grid and the button inside the grid I have on my screen. It is within many layers of Grids and StackLayouts, which have varying paddings.
I have tried using absolute layout, but it never puts the control i'm trying to draw over it in the correct place.
Grid g = new Grid;
g.BackGroundColor = Color.Pink;
g.WidthRequest = 48;
g.HeightRequest = 48;
g.VerticalOptions = LayoutOptions.Start;
g.HorizontalOptions= LayoutOptions.Start;
g.TranslationX = AbsoluteLayout.GetLayoutBounds(LeftButton).Location.X;
g.TranslationY = AbsoluteLayout.GetLayoutBounds(LeftButton).Location.Y;
PageSizedGrid.Children.Add(g);
We are implementing a picture viewer with zoom in based on center of the image with scroll options.
We have used Forms.Panel with a picture box control for displaying the image and auto scroll set to true.
In order to implement zoom we are using inflate function but this will redraw the image to top left:
To bring it to center we are setting the scroll position to center using the following code:
Rectangle rc = this.Panel_PicBox.ClientRectangle;
Point ScrollPosition = this.Panel_PicBox.AutoScrollPosition;
int height = (int)(PictureBox_png.Height);
int width = (int)(PictureBox_png.Width);
if (rc.Width < width)
ScrollPosition.X = (width - rc.Width) >> 1;
if (rc.Height < height)
ScrollPosition.Y = (height - rc.Height) >> 1;
Point p = new Point(ScrollPosition.X,ScrollPosition.Y);
this.Panel_PicBox.AutoScrollPosition = p;
The code works perfectly for bringing the image to center, only problem is we see a lot of flickering when the scroll position is set.
We have tried double buffer method to reduce flickering but didnt work. Please suggest if there is any other method to reduce flickering.
I have a Windows Forms application which is using a FlowLayoutPanel control to display a Picture boxes that are built dynamically. I have enabled the drag drop effect as they may want to reorder them, this works fine with only a few picture boxes (right now the screen shows about 6) but if there are more you try to drag an item below the control it will not scroll, so you cannot put an image that is currently on the screen (say image 4) to an image that is below what is visible (say image 13).
I have seen several posts where the ScrollControllIntoViewMethod should be used, I have tried in a few spots unsuccessfully.
Thanks!
Here is what I ended up doing.
Create the event on the DragLeave event
Getting the position of the control
Calculating the height of the control to get the lower boundary.
check the mouse position and if above the bounds, change the vertical scroll (or horizontal scroll) by a value in a Constant..
private void thumbFlow_DragLeave(object sender, EventArgs e)
{
int BegY_ThumbFlow = this.thumbFlow.FindForm().PointToClient(this.thumbFlow.Parent.PointToScreen(this.thumbFlow.Location)).Y;
int thumbFlowBound_Y = this.thumbFlow.Height + BegY_ThumbFlow;
int mouseY = this.thumbFlow.FindForm().PointToClient(MousePosition).Y;
while (mouseY >= thumbFlowBound_Y)
{
thumbFlow.VerticalScroll.Value = thumbFlow.VerticalScroll.Value + DRAG_DROP_SCROLL_AMT;
mouseY = thumbFlow.FindForm().PointToClient(MousePosition).Y;
thumbFlow.Refresh();
}
while (mouseY <= BegY_ThumbFlow)
{
thumbFlow.VerticalScroll.Value = thumbFlow.VerticalScroll.Value - DRAG_DROP_SCROLL_AMT;
mouseY = thumbFlow.FindForm().PointToClient(MousePosition).Y;
thumbFlow.Refresh();
}
}
Hope this helps others.