|
Please suggest me with ideas and code to place a dialog bar in the middle of a window.
|
|
|
|
|
|
Thanks for the reply. Which function is used to reposition the dialogbar.
SetWindowPos is not making any changes in the position for the dialogbar.
Please advice.
|
|
|
|
|
|
It's not doing any changes.
m_SysWnd.MoveWindow(100,100,100,100,true); //New positions
Am I missing anything?
|
|
|
|
|
manoharbalu wrote:
Am I missing anything? Without seeing all the relevant code, we would be guessing at best.
What is m_SysWnd ? Where are you calling MoveWindow() from?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
|
I have just run a simple test and it works fine. The only difference is that I am using basic Win32 rather than MFC.
|
|
|
|
|
Here is what I have:
RECT rectParent, rectDialog;
SIZE sizeParent, sizeDialog;
POINT point;
GetWindowRect(hDialog, &rectDialog);
sizeDialog.cx = rectDialog.right - rectDialog.left;
sizeDialog.cy = rectDialog.bottom - rectDialog.top;
GetClientRect(GetParent(hDialog), &rectParent);
sizeParent.cx = rectParent.right - rectParent.left;
sizeParent.cy = rectParent.bottom - rectParent.top;
point.x = (sizeParent.cx - sizeDialog.cx) / 2;
point.y = (sizeParent.cy - sizeDialog.cy) / 2;
ClientToScreen(GetParent(hDialog), &point);
MoveWindow(hDialog, point.x, point.y, sizeDialog.cx, sizeDialog.cy, true);
modified 18-Dec-18 12:39pm.
|
|
|
|
|
Thanks for your reply. I have changed the same code which you had sent to MFC as shown below. But still its not working. Please help me what is wrong..?
// MainFrm.h
CSysWindow m_SysWnd; //CSysWindow derived from CDialogbar
// MainFrm.CPP
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (!m_SysWnd.Create(this, IDD_SYS2,CBRS_TOP|CBRS_FLYBY|CBRS_TOOLTIPS, IDD_SYS2))
{
TRACE0("Failed to create DlgBar\n");
return -1; // fail to create
}
m_SysWnd.SetBarStyle( m_SysWnd.GetBarStyle()|
CBRS_ALIGN_TOP|CBRS_BORDER_TOP | CBRS_FLOAT_MULTI );
m_SysWnd.AttachCtrls(); //To Attach the Combo box to the control bar window
RECT rectParent, rectDialog;
SIZE sizeParent, sizeDialog;
POINT pointNew;
HWND hDialog = m_SysWnd.m_hWnd;
CWnd * hParentWnd = m_SysWnd.GetParent();
// get the size of the dialog
m_SysWnd.GetWindowRect(&rectDialog);
sizeDialog.cx = rectDialog.right - rectDialog.left;
sizeDialog.cy = rectDialog.bottom - rectDialog.top;
// get the size of the parent Window's client area
hParentWnd->GetClientRect(&rectParent);
sizeParent.cx = rectParent.right - rectParent.left;
sizeParent.cy = rectParent.bottom - rectParent.top;
// parent's sizes minus dialog's sizes divided by 2
// give the coordinates of the centre position
pointNew.x = (sizeParent.cx - sizeDialog.cx) / 2;
pointNew.y = (sizeParent.cy - sizeDialog.cy) / 2;
// we need to make parent coordinates relative to the screen
hParentWnd->ClientToScreen(&pointNew);
// now move the Window to the new position
m_SysWnd.MoveWindow(pointNew.x, pointNew.y, sizeDialog.cx, sizeDialog.cy, true);
|
|
|
|
|
MFC handles the docking state and sizing of control bars.
Your code does not show that you are docking the control bar; are you?
After creation of m_SysWnd:
m_SysWnd.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY); // CMainFrame enable docking
DockControlBar(&m_wndDlgBar); // CMainFrame dock control bar
As far as moving the bar to a specific location look at CMainFrame::FloatControlBar()
which undocks the controlbar and allows for positioning.
FloatControlBar(&m_SysWnd,CPoint(100,100));
In regards to resizing the bar, you will probably have to provide some implementation of
CDialogBar::CalcFixedLayout() or CDialogBar::CalcDynamicLayout() override which provides size info.
CSize CSysWindow::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
{
if (bStretch) // if not docked stretch to fit
{
// This is a fixed size. You will have to provide your own implementation.
return CSize(100,100);
//return CSize(bHorz ? 32767 : m_sizeDefault.cx,
// bHorz ? m_sizeDefault.cy : 32767);
}
else
return m_sizeDefault;
}
A Google search on these functions may help.
Best regards.
-- modified 19-Dec-18 7:02am.
|
|
|
|
|
Sorry, this is the correct code:
CSize CSysWindow::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
{
if (bStretch) // if not docked stretch to fit
{
return CDialogBar::CalcFixedLayout(bStretch, bHorz);
}
else
// This is a fixed size. You will have to provide your own implementation.
return CSize(100,100);
}
|
|
|
|
|
Thanks for your kind reply.
Please help me to create a single window that has the following in the client area:
1. Dialog bar on top (used as a toolbar)
2. A view to display a graph trend (Updated every cycle)
3. After the above view, a Dialog bar to be placed. (Used as a tool bar)
4. A Grid control to display set of values which will be updated every cycle.
As I am not an expert into this, Please guide me steps to create the above window and update it every cycle as defined.
|
|
|
|
|
Sorry, the group does not write code for you. See How to Ask a Question at the top.
If you are not familiar with these tasks, you need to get training on programming in MFC.
I've learned a lot just by using Google to search for tasks I want to perform in MFC and
in many cases finding example code that helped me get the task done. If you write code to
perform a task and it doesn't work as expected, then ask the group for help with the
particular section of your code that isn't working and they will help you; like you did with
your current question.
Best regards
|
|
|
|
|
Sorry for that. As you said I will refer google. Thanks
|
|
|
|
|
I cannot see anything obvious in your code, although you may need to put that code at a later point; perhaps in the toolbar's OnCreate method. Looking at the documentation it suggests that a CToolBar should include the WS_CHILD style at creation, but you do not include that. Unfortunately I do not use MFC so I cannot recreate your situation.
If it still does not work then you will need to use your debugger to see what is happening.
|
|
|
|
|
My task is to make a function to append int to char*, using C style and end up with char*. No string etc.
I have it partially figured out - see attached code.
I have some understanding how passing by value works, but not sure how to actually code / use the strcat - the "all concatenated / done " part and use it in main code.
<pre>
char * CLASS_LCM1602::BuildMessage(char *&title, int value) {
char buffer[100];
snprintf(buffer, sizeof(buffer), "%d", value);
#ifdef DEBUG
cout << " conversion int to char buffer " << +buffer << endl; #endif
char FullMessage[100];
strcpy(FullMessage, title);
cout << "title copy " << FullMessage << endl;
strcat(FullMessage, buffer);
cout << "full message " << FullMessage << endl;
this is where I need some help
this does not makes sense to me
it compiles , does not execute
strcpy(title, FullMessage);
cout << "title " << title << endl;
exit(1);
return FullMessage; }
The function call
<pre>
char *title = "NEW TEST";
int value = 100;
char *message = i2c.BuildMessage(title, value);
here is the desired result code
never gets here
cout << " pass full message "<< +title << endl;
#endif
Any ( factual ) help will be appreciated.
Cheers
Vaclav
|
|
|
|
|
Please state clearly what are your requirements: you wrote
Quote: y task is to make a function to append int to char*, using C style and end up with char* but then you are using C++ stuff and the snprintf , strcopy , etc. functions.
In a pure-C approach you have (basically) two alternatives:
- Passing a buffer containing the source string, but also large enought to contain the target one.
- Pass only the source string, and return a freshly allocated buffer containing the target one. Then it is caller task to eventually release the memory.
|
|
|
|
|
You could reduce the number of buffers you are using, as that seems to complicate your code. You are also trying to return FullMessage which is a temporary buffer inside the function. So as soon as you return from the function that buffer's memory space is free to be overwritten. And what is that exit(1) call there for? No wonder you never return from your function. You need something simple like (using C style only):
#define MAX_BUFFER 100
char * CLASS_LCM1602::BuildMessage(char *title, int value)
{
char* buffer = (char*)malloc(MAX_BUFFER );
snprintf(buffer, MAX_BUFFER , "%s %d", title, value);
return buffer;
}
And then the call is:
char *message = i2c.BuildMessage(title, value);
printf("%s\n", message);
free(message);
modified 17-Dec-18 5:03am.
|
|
|
|
|
Quote: snprintf(buffer, sizeof(buffer), "%s %d", title, value); // this assumes 100 characters is enough That should be
snprintf(buffer, 100, "%s %d", title, value);
|
|
|
|
|
|
Thanks,
so I goofed by not allocating space / format for the "concatenated " message.
Since this is just basic "title value " function the new buffer should not be fixed / defined. I am planning to pass more values with same title later.
But it is a good practice not to allocate more than necessary, right?
Thanks again.
|
|
|
|
|
Yes, otherwise you tend to duplicate effort and waste space. In fact my code relies on the total generated string being less than 100 characters, and could fail for longer titles. A better way of doing it would be to measure the fields that are to be entered to ensure you have enough space. Something like:
char * CLASS_LCM1602::BuildMessage(char *title, int value)
{
int bufferSize = strlen(title) + 1 + strlen("-2147483647") + 1; char* buffer = (char*)malloc(bufferSize);
snprintf(buffer, bufferSize, "%s %d", title, value);
return buffer;
}
|
|
|
|
|
Personally code in this form I would not allow in our code base as it will lead to bleeding memory when used by others.
It is not clear that the function allocates memory, to anyone other than yourself and not being aware the function setups to use the char* pointer return and lose it ... take this basic code
CLASS_LCM1602 myCLASS_LCM1602 = .. some initialization;
/* now use your function */
std::cout << myCLASS_LCM1602.BuildMessage("Demo my Title", 10) << "\n";
That bleeds memory and the whole setup of the function encourages it because people will be tempted to feed the return char* value into functions.
For my 2 cents I would force you to use this interface for what you wanted to do .. Joe below has made the same comment.
int CLASS_LCM1602::BuildMessage(const char *title, int value, char* buffer, int bufSize)
It is much cleaner in that they pass you a buffer to fill and it's size and you return how many characters you put in the buffer.
Both you and they can be safe about handling the string becasue all sizes are known both directions.
If they want to allocate a buffer they can but they then know they have responsibility to dispose it.
It is also more flexible because you can use it on temporary stack allocated buffers .. something like this is a perfectly valid temp buffer with no allocate required.
char tempBuf[256];
As an example the actual Windows framework MFC is copying does exactly that
GetWindowTextA function | Microsoft Docs[^]
In vino veritas
modified 18-Dec-18 0:59am.
|
|
|
|
|
Note that title is a static string, not a buffer; you cannot safely append to it.
Your prototype should be more like:
BuildMessage(const char* pTitle, int value, char* pDstBuffer, size_t dstBufferLen); Also note that you are doing an snprintf, but aren't using strncat.
|
|
|
|
|
When I started I actually had two function steps - convert value int to char* then strcat the title and value.
It did not work so I inserted strcpy, but forgot the build resulting buffer.
snprintf was just to do conversion.
Now it does it all in few lines of code.
Thanks to the forum. Appreciate it.
|
|
|
|
|