Align DialogBar in Frame and set its width - layout

I'm working on an MFC project which was transferred to me.
It's basic layout (main frame derived from CFrameWnd) is shown in this sketch:
The CommandBar and the ControlBar, both derived from CDialogBar, were created using WS_CHILD | CBRS_ALIGN_RIGHT as style.
This is fine for the alignment. But I would like to define the widths of these two elements and cannot find a way to set it.
When I tried to EnableDocking for the dialog bars, I couldn't manage to resolve the assertions. Also I'm not sure if this is what I am looking for.

Overriding CalcDynamicLayout and returning the calculated size is what I was looking for.
Example:
CSize CommandBar::CalcDynamicLayout(int nLength, DWORD dwMode)
{
CSize size;
CRect parentRect;
if (GetParent())
GetParent()->GetClientRect(&parentRect);
size.cy = parentRect.Height();
size.cx = (int)(abs(parentRect.Width() - parentRect.Height() + GetSystemMetrics(SM_CYMENUSIZE)) * 0.5);
return size;
}

Related

Modifying parent classes variables

Iv looked around online for a solution to this issue but iv been unable to solve it.
I want to extend the sprite class to make my own interactive circle. Everything works but setting the X,Y, Width and height of the custom class does not work:
class CircleDraw extends Sprite
{
public function new(x:Int,y:Int,width:Int,height:Int)
{
super();
this.x = x;
this.y = y;
this.width = width;
this.height = height;
drawCircle();
}
private function drawCircle()
{
this.graphics.beginFill(0xffffff);
this.graphics.drawCircle(this.x,this.y, this.width);
this.graphics.endFill();
}
}
The approach above does not work as expected, setting x,y and width via the constructor results in literally nothing appearing. Yet if i set them manually, either within the class
this.graphics.drawCircle(200,200, 30);
Or prior to addChild:
circle = new CircleDraw(10,10,100,200);
circle.x=100;
circle.y=100;
it then appears on screen. also after adding it like so once the values have been added manually within the class rather than this.x etc:
circle = new CircleDraw(10,10,100,200);
addChild(circle);
So my question is this, how do i extend a class (Sprite) and allow the constructor to modify its parents default variables and keep the values?
EDIT
Just to provide all the code as requested:
This does not work:
circle = new CircleDraw(10,10,100,200);
addChild(circle);
when Circle draw is like this:
class CircleDraw extends Sprite
{
public function new(x:Int,y:Int,width:Int,height:Int)
{
super();
this.x = x;
this.y = y;
this.width = width;
this.height = height;
drawCircle();
}
private function drawCircle()
{
this.graphics.beginFill(0xffffff);
this.graphics.drawCircle(this.x, this.y, this.width);
this.graphics.endFill();
}
}
It does work if i modify the method:
private function drawCircle()
{
this.graphics.beginFill(0xffffff);
this.graphics.drawCircle(200, 200, 30);
this.graphics.endFill();
}
Or if during the instancing of the object i set the X and Y variables as mentioned before the edit.
You are indeed setting the base class variables successfully, it's just that DisplayObject.width has a rather specific (and perhaps not that obvious) behavior.
width:Float
Indicates the width of the display object, in pixels. The width is calculated based on the bounds of the content of the display object. When you set the width property, the scaleX property is adjusted accordingly, as shown in the following code:
Except for TextField and Video objects, a display object with no content(such as an empty sprite) has a width of 0, even if you try to set width to a different value.
—OpenFL API: DisplayObject: width
In this sense, OpenFL follows the ActionScript 3.0 API.
From what I can surmise, it looks like you're trying to override a constructor (new) that takes no arguments.
I'm not entirely sure, but that might not get you what you want. What I think you're actually doing is just creating a method "new" on the extended class, and then within it, feeding the parent nothing (super()). So the parent will not have the constructor arguments. It would be interesting to do look at that object in a debugger and look at the instance properties vs. the parent ones.
There's probably a way around that, but I think you might want to look at doing this via composition instead of inheritance. For example, in "new", create a new instance of a sprite, and manipulate the properties of that.
class MySprite
{
public var sprite : Sprite;
public function new ( ) {
sprite = new Sprite ();
}
}
You would then perform your operations on that sprite instance. Essentially, you are just wrapping a sprite in your own class. Decorator, more or less.
I found some reference to the topic here (it's been a while since I did any Flash programming), it shows addChild and removeChild implementations, etc.
http://old.haxe.org/forum/thread/685
From the (partial) code you posted, it looks it should work.
In other words, setting parent's variables like that should work.
I doubt there are some other code you didn't post gets in the way. I suggest you print out the x, y values in the drawCircle call to debug.
I also doubt the circle is drawn off-screen so you can't see it. Because you first moved the sprite, to (x,y) and then draw a circle in (x,y) inside the sprite. So effectively the circle is at (2x,2y) in global space
EDIT:
this.graphics.drawCircle(200,200, 30);
You claim this worked. Should draw at (210,210) with radius 30
circle = new CircleDraw(10,10,100,200);
circle.x=100;
circle.y=100;
You claim this worked. Should draw at (200,200) with radius 100
circle = new CircleDraw(10,10,100,200);
addChild(circle);
You claim this didn't work. Should draw at (20,20) with radius 100
From the above three version, you are actually drawing at different places with different sizes. So I still suspect that "didn't work" may due to the fact that you are drawing at some places not in sight.
So I still suggest you print out the value of x, y, width inside the private drawCircle function to see what's happening
Be aware, that you are kind of dealing with 2 coordinate spaces. The one were the Sprite will be added and the graphics object of that Sprite. If you set this.x and this.width you are actually setting properties of this Sprite. So in regards of positing you are moving the Sprite itself in that case. The Sprite "graphics" property has it's own coordinate space.
For example if you pass x=100 in your CircleDraw constructor function you are first moving the sprite itself by x=100 and then draw the circle with an x offset of 100. So if you would add the sprite directly to the Stage you would start drawing your circle actually at x=200, because you effectively applied the position twice. It seems to me this is not what you actually are intending.
Also your CircleDraw instance (which is also a Sprite of course) is "empty" when you are constructing it. So calling this.width = width in your constructor has no effect. this.width will stay 0 because the Sprite has no contents at that point. So in the drawCircle method you are drawing a circle with a width of 0.
Probably the better solution would be to simply pass the arguments of your constructor function to your drawCircle function, without setting any properties.

Direct3D Window->Bounds.Width/Height differs from real resolution

I noticed a strange behaviour with Direct3D while doing this tutorial.
The dimensions I am getting from the Window Object differ from the configured resolution of windows. There I set 1920*1080, the width and height from the Winows Object is 1371*771.
CoreWindow^ Window = CoreWindow::GetForCurrentThread();
// set the viewport
D3D11_VIEWPORT viewport = { 0 };
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = Window->Bounds.Width; //should be 1920, actually is 1371
viewport.Height = Window->Bounds.Height; //should be 1080, actually is 771
I am developing on an Alienware 14, maybe this causes this problem, but I could not find any answers, yet.
CoreWindow sizes, pointer locations, etc. are not expressed in pixels. They are expressed in Device Independent Pixels (DIPS). To convert to/from pixels you need to use the Dots Per Inch (DPI) value.
inline int ConvertDipsToPixels(float dips) const
{
return int(dips * m_DPI / 96.f + 0.5f);
}
inline float ConvertPixelsToDips(int pixels) const
{
return (float(pixels) * 96.f / m_DPI);
}
m_DPI comes from DisplayInformation::GetForCurrentView()->LogicalDpi and you get the DpiChanged event when and if it changes.
See DPI and Device-Independent Pixels for more details.
You should take a look at the Direct3D UWP Game templates on GitHub, and check out how this is handled in Main.cpp.

resize issue CListBox inside SDI application with CWnd derived child

I am having a problem with the size of the CListBox that is suppose to cover all the client area of the SDi application.
My Main Window looks as shown below:
As you can clearly see that the list box does not cover the whole client area.
The following is what I am doing in on size of the CWnd derived class:
void CLogWnd::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
m_pWndLogList->SetWindowPos(NULL, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER);
}
CLogWnd is the main window that fill all the area of the CMainFrame.
Give your listbox LBS_NOINTEGRALHEIGHT style. Without it, the box wants to have a height that's an exact multiple of a row height.

Creating UI dynamically in android

I want to make UI for tablet like shown in images.This UI will repeat according to number of items. And the position of each block (i.e small or big block) can change dynamically. Please give me suggestion which view,layout i should use.
Any suggestion would be appreciated...thanks in advance.
If you are targeting a API v14 or above, you can use GridLayout: http://developer.android.com/reference/android/widget/GridLayout.html
Using LinearLayout where each category is added and using RelativeLayout for each category is a good option. You should customize onlayout method of the relative layout as a function of number of products it contains.
You can use fragments, listview as well.
EDIT after image change: You can just extend relativelayout and override onLayout method. This will perform better than nested layouts and I can't think of anything else you can get away with less effort.
EDIT for elaboration:
Here is an example class I use. Basically in the onlayout method you make every decision and tell all the child views to lay them in a rectangle by calling layout method of each of them and passing the parameters of the rectangle. See how I use layout method of child view to dictate the rectangle.
public class KnockPile extends HandPile
{
private static final String TAG = "KnockPile";
static final int EXPECTED_CARDS = 3;
int mColoring; // this is the coloring group this pile is associated with.
// every card added to this pile should be set with this color.
public KnockPile(Context context, GameActivity ref , int ingroup)
{
super(context );
mColoring = ingroup;
mActivityReference = ref;
setWillNotDraw(false);
setClickable(true);
setOnDragListener(this);
mCardBorders = new ArrayList<Integer>();
final LayoutTransition transition = new LayoutTransition();
setLayoutTransition(transition );
//transition .enableTransitionType(LayoutTransition.CHANGING);
//transition .disableTransitionType(LayoutTransition.CHANGE_APPEARING);
}
/**
* this overrides the card ordering of handpile. This method lays the cards in a linear fashion.
* Possibly overlapping fashion. This is not dependent to orientation of screen.
*
* #see com.kavhe.kondi.gin.layouts.HandPile#onLayout(boolean, int, int, int, int)
*/
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int availablewidth = getMeasuredWidth() ;//this is the maximum availlable
int distance = availablewidth /Math.max(getChildCount(), 1) ; // the horizontal distance between two cards
Log.v(TAG,"available width onlayout is :" + availablewidth +"and distance is " + distance);
int cardheight = getHeight();
int cardwidth = cardheight*3/4;
if(distance > cardwidth) distance = cardwidth;
mCardBorders.clear();
for(int i = 0 ; i < mCards.size() ; i++)
{
//save this border into a global variable so that it can be used when one of the cards dragged
//by user to show that user can insert to that location
mCardBorders.add( i*distance);
mCards.get(i).layout( i*distance , 0 , cardwidth+ i*distance , cardheight);
}
}
}
and this is from documentation
protected void onLayout (boolean changed, int left, int top, int right, int bottom)
Called from layout when this view should assign a size and position to each of its children. Derived classes with children should override this method and call layout on each of their children.
Parameters
changed This is a new size or position for this view
left Left position, relative to parent
top Top position, relative to parent
right Right position, relative to parent
bottom Bottom position, relative to parent
It is also possible through table layout with its row span property
Are the "products" always going to fit nicely on lines as you have drawn? If then, you can use LinearLayouts (Vertical and Horizontal) nested in each other.
To design such UIs for Tablets you should use Fragments and inside the fragment add/remove your respective layouts. If you are taking Relative Layouts then proper usage of RelativeLayout.LayoutParams is required.
If you are looking for a best example which uses Fragments try Google IO app source. It uses various dynamic UI features.
Hope it helps !
With the help of StaggeredGridView I sloved my requirement.
Thanks to all for help and support.

C++ MFC scrollbar cannot scroll

I am trying to implement a zoom in function to my app.
The idea is when I chose to zoom in, the graph should expand horizontally 2 times larger so that only half of the graph will be shown in the window, and one will need to scroll to see the other half despite the size of the window.
I have a zoom variable for zoom factor. Then in onDraw(CDC &pDC):
//...set pen and others...
CRect rect;
GetClientRect(rect);
for (int x=0; x < zoomFactor*rect.Width(); x++)
//....draw the graph
then in onToolsZoomin():
void CMyGraphView::OnToolsZoomin()
{
zoom *= 2;
CRect rect;
GetClientRect(rect);
CSize sizeTotal;
sizeTotal.cx = zoom*rect.Width();
sizeTotal.cy = 0;
SetScrollSizes(MM_TEXT, sizeTotal);
this->RedrawWindow();
}
When I run this, I can have the window correctly draw half of the graph and a scrollbar that indicate only half of the graph is shown. But when I try to scroll it, it goes back to the original position (bottom left) and the other half of the graph won't show up.
The parameters in both functions are not the same one. It can be the first reason of the problem.
Can you put the code that is suppose to call OnToolsZoomin please ? Is it handled through a WM_VSCROLL or WM_HSCROLL message ?
Is your function OnToolsZoomin called at all ?
Is you scrollbar properly initialized (scroll range) ?

Resources