I create tab with createwindow. I have 2 tab item and I want to create some static window in 2 tab item. I have use createwindow with parent is the handle to tab. But the child window is present in both tab1 and tab2. I want 2 tab item have a different content. So How can I do that.
Is there another way to create a Static control belong to the specific tab1 or tab 2 ...
Not hwnd of tab from create window. I don't know how to do that so this is my solution
I use win api
Thanks
Here some of my code
TabCtrl_InsertItem(hwndTab,0,&tcitem);
TabCtrl_InsertItem(hwndTab,1,&tcitem);
hwndTab_1_1_1 = CreateWindow(L"BUTTON",L"sample",WS_CHILD|WS_VISIBLE,0,29,100,50,hwndTab,(HMENU)4,hInstance,NULL);
hwndTab_1_2_1 = CreateWindow(L"BUTTON",L"sample2",WS_CHILD|BS_AUTOCHECKBOX,20,80,100,50,hwndTab,(HMENU)4,hInstance,NULL);
and I'm using this:
case WM_NOTIFY:
if (((LPNMHDR)lParam)->code == TCN_SELCHANGE) {
switch(TabCtrl_GetCurSel(hwndTab)) {
case 0:
ShowWindow(hwndTab_1_1_1,SW_SHOW);
ShowWindow(hwndTab_1_2_1,SW_HIDE);
break;
case 1: //
ShowWindow(hwndTab_1_1_1,SW_HIDE);
ShowWindow(hwndTab_1_2_1,SW_SHOW);
break;
default: return DefWindowProc(hwnd, Message, wParam, lParam);
}
}
else {
return DefWindowProc(hwnd, Message, wParam, lParam);
}
break;
I need the code to the same thing with these code. I don't want to use to much show and hide too many time if we have many child window.
you can try like this:
assume you have 3 tab pages.
T *pTabPage[3]; point to your 3 tab pages;
int nCurrentPage; to save your current tab page.
and when you want to change the tab page,
1.hide the "current page" that saved in the nCurrentPage: ShowWindow(pTabPage[nCurrentPage], SW_HIDE);
2.Get the really current page: nCurrentPage = GetCurSelect();
3.Show the really current page: ShowWindow(pTabPage[nCurrentPage], SW_SHOW);
the code is incorrect, just to explain the method
Hope to help you!
Related
Use Vistual Studio 2012 or up
Create a MFC project
In the Wizard, set to Multiple document project
Set to Office style
Run it.
Click new button to create some empty documents.
Now I want to know how to change tab's header backcolor in these empty documents?
You can disable auto-color in MainFrm.cpp
int CMainFrame::OnCreate(...)
{
//...
mdiTabParams.m_bAutoColor = FALSE; // set to FALSE to disable auto-coloring of MDI tabs
}
Perhaps you knew about that already! To change the tab's background color to something specific can be very tricky because it's all tied in to the selected theme. But you can do it, for example by the following method:
ON_REGISTERED_MESSAGE(AFX_WM_CHANGING_ACTIVE_TAB, &CMainFrame::OnAfxWmChangingActiveTab)
LRESULT CMainFrame::OnAfxWmChangingActiveTab(WPARAM wParam, LPARAM lParam)
{
CMFCTabCtrl* tab = (CMFCTabCtrl*)lParam;
if (tab)
tab->SetTabBkColor(wParam,RGB(255,0,0));
return 0;
}
You can also disable the tab colors by the following code:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if(-1 == CMDIFrameWndEx::OnCreate(lpCreateStruct))
return -1;
....
CMFCTabCtrl& MFCTabCtrl = GetMDITabs();
MFCTabCtrl.EnableAutoColor(FALSE);
....
I have been tasked with assigning tooltips to each item in a configuration menu. I have completed "adding" the tooltip to each control on the page, but it seems sometimes the tooltip shows up and sometimes it does not, depending on the position of the control on the screen.
To tooltip-erize the pages I first
EnableToolTips(TRUE);
In each CPropertyPage's OnInitDialog method.
I then add the notification map
ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnToolTipText)
With the function OnToolTipText looking as such
BOOL CCfgPrefPage::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
UINT nID = pNMHDR->idFrom;
if (pTTT->uFlags & TTF_IDISHWND)
{
nID = ::GetDlgCtrlID((HWND)nID);
if(nID)
{
if( nID == GetDlgItem(IDC_PICKDIST_EDIT)->GetDlgCtrlID())
_tcsncpy_s(pTTT->szText, _T("Tool Tip Text"), _TRUNCATE);
else if( nID == GetDlgItem(IDC_ENDPTTOL_EDIT)->GetDlgCtrlID())
_tcsncpy_s(pTTT->szText, _T("Tool Tip Text"), _TRUNCATE);
pTTT->lpszText = pTTT->szText; // Sanity Check
pTTT->hinst = AfxGetResourceHandle(); // Don't think this is needed at all
return TRUE;
}
}
return FALSE;
}
It seems for some of my controls the tool tip will not show up. For most of the check box controls the tool tip displays, but for a few they just do not show. There are no other controls covering them up, they are not disabled.
Another thing, if I use the non-standard cursor windows repeatedly flashes the tool tip, so much so it is unreadable in some cases. How can I fix this? This is not a problem on CEdit controls, so why is it a problem elsewhere?
EDIT: Update, the controls that have been on the pages for years seem to show tool tips. Any control that I try to add now/today will not show tool tips at all. No matter the position, control type, settings, I cannot get a single tool tip to show on a newly inserted control.
If you do not want to use helper class I have proposed then fix the problems in your code.
First, use ON_NOTIFY_EX_RANGE macro when mapping the even handler, like this (this will cover all IDs):
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
Next, you need to fix your function. I see a few problems here. First, when testing for TTF_IDISHWND flag you only need to re-initalise the nID. You do not need to apply this to the whole function. Second, after all manipulations, your nID will be the actual dialog ID. There is no need to GetDlgItem() function
BOOL CCfgPrefPage::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
UINT nID = pNMHDR->idFrom;
if (pTTT->uFlags & TTF_IDISHWND)
{
nID = ::GetDlgCtrlID((HWND)nID);
}
if(nID)
{
if( nID == IDC_PICKDIST_EDIT)
_tcsncpy_s(pTTT->szText, _T("Tool Tip Text"), _TRUNCATE);
else if( nID == IDC_ENDPTTOL_EDIT)
_tcsncpy_s(pTTT->szText, _T("Tool Tip Text"), _TRUNCATE);
//pTTT->lpszText = pTTT->szText; // Sanity Check
*pResult = 0;
return TRUE;
}
return FALSE;
}
Working with a toolbar which repeats some menu items from menus of an older MFC application, I have worked on this issue of tool tips as well as (1) modifying the toolbar bit map to include additional icons and (2) providing user feedback on current application state. My problem is that I have to do most of this by hand rather than using the various wizards and tools.
What I have done is to (1) add new members to the CView derived class to handle additional messages, (2) modified the toolbar bit map to add in the additional icons using both MS Paint and the Resource Editor, and (3) added new event ids and event handlers to the message map for the CView derived class.
One problem I ran into with the toolbar bitmap change was that since I was inserting an icon, I had to shift an existing icon in the bitmap to the right. My first attempt at this resulted in the shifted icon showing as a blank on the application toolbar. Then I realized that I needed to add a bit more to the length of the toolbar bitmap. After adding a couple more columns to the last icon in the toolbar bitmap to make it a standard width in pixels, the icon displayed properly.
For tooltips I added the following to the message map:
ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnToolTipText)
I then added the following method to my class to handle the notifications for my menu items. As a side note, it appears that OnToolTipText() is the standard method used in CFrameWnd class and CMDIChildWnd class however CView derives from CWnd as does CFrameWnd so I doubt it makes a difference as to what the method is named.
inline BOOL CPCSampleView::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
static wchar_t toolTextToggleExportSylk [64] = L"Toggle SYLK export.";
static wchar_t toolTextClearWindow [64] = L"Clear the log displayed.";
static wchar_t toolTextConnectLan [64] = L"Log on the POS terminal through the LAN.";
TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
switch (pNMHDR->idFrom) {
case ID_TOGGLE_SYLK_EXPORT:
pTTT->lpszText = toolTextToggleExportSylk;
return TRUE;
case ID_WINDOW_CLEAR:
pTTT->lpszText = toolTextClearWindow;
return TRUE;
case ID_CONNECT_LAN_ON:
pTTT->lpszText = toolTextConnectLan;
return TRUE;
}
// if we do not handle the message then return FALSE to let someone else do it.
return FALSE;
}
For the user feedback on a menu item which toggles a file export when doing reports I provided the following changes to the message map and then implemented the necessary methods. There are two types of messages involved so I had to add two methods and two new message map entries:
// New message map entries to handle the menu item selection event
// and to update the menu item and the toolbar icon with state changes
ON_COMMAND(ID_TOGGLE_SYLK_EXPORT, OnToggleExportSylk)
ON_UPDATE_COMMAND_UI(ID_TOGGLE_SYLK_EXPORT, OnUpdateToggleExportSylk)
// New methods added to the CView derived class
// handle the menu selection event generated by either selecting the menu item
// from the menu or by clicking on the icon in the toolbar.
void CPCSampleView::OnToggleExportSylk()
{
// Exclusive Or to toggle the indicator bit from 0 to 1 and 1 to 0.
GetDocument()->ulReportOptionsMap ^= CPCSampleDoc::ulReportOptionsExportSylk;
}
// handle the request from the MFC framework to update the displayed state this
// not only does a check mark against the menu item it also causes the toolbar
// icon to appear depressed if click is set or non-depressed if click is not set
inline void CPCSampleView::OnUpdateToggleExportSylk (CCmdUI* pCmdUI)
{
if (GetDocument()->ulReportOptionsMap & CPCSampleDoc::ulReportOptionsExportSylk)
{
// SYLK export is turned on so indicate status to the user. This will
// put a check mark beside the menu item and show the toolbar button depressed
pCmdUI->SetCheck (1);
}
else
{
// SYLK export is turned off so indicate status to the user. This will
// remove the check mark beside the menu item and show the toolbar button as raised.
pCmdUI->SetCheck (0);
}
}
The resource file changes were needed to provide a new button for the toggle action as well as to add a new menu item for the toggle action. I am using the same resource id for several different things since these are all separate. So the id for the resource string is the same as for the menu item and is same for the toolbar button so as to simplify my life and make it easy to find all the particular bits and pieces.
The toolbar resource file definition looks like:
IDR_MAINFRAME TOOLBAR 16, 15
BEGIN
BUTTON ID_CONNECT_LAN_ON
SEPARATOR
BUTTON ID_WINDOW_CLEAR
SEPARATOR
BUTTON ID_TOGGLE_SYLK_EXPORT
SEPARATOR
BUTTON ID_APP_ABOUT
END
And the specific part of the menu, which uses the same resource id for the toggle event id looks like:
MENUITEM "Export to SYLK file", ID_TOGGLE_SYLK_EXPORT
Then to provide the status bar text which shows up with a mouse over there is a string table addition:
ID_TOGGLE_SYLK_EXPORT "Toggle export of SYLK format report files for spreadsheets."
The lpszText member of the struct is describe in the MSDN documentation for the TOOLINFO struct as:
Pointer to the buffer that contains the text for the tool, or
identifier of the string resource that contains the text. This member
is sometimes used to return values. If you need to examine the
returned value, must point to a valid buffer of sufficient size.
Otherwise, it can be set to NULL. If lpszText is set to
LPSTR_TEXTCALLBACK, the control sends the TTN_GETDISPINFO notification
code to the owner window to retrieve the text.
Reviewing the existing answer to this question, I wondered about the if statement check for the TTF_IDISHWND flag. The MSDN documentation for the TOOLINFO struct has this to say:
Indicates that the uId member is the window handle to the tool. If
this flag is not set, uId is the tool's identifier.
I want to post a message to all views.
I'm considering get a Document global reference and then implement a method like below
void SomeAppDoc::DispatchToAll( UINT msg, WPARAM wP, LPARAM lP )
{
//some how get all view's reference
//iterate and update each views
}
What is the effective way?
The simplest way is to call CDocument::UpdateAllViews, which calls the OnUpdate function of each view attached to the document.
If you really need to post a message to each view, rather than call OnUpdate, do something similar to UpdateAllViews:
void SomeAppDoc::DispatchToAll(UINT msg, WPARAM wParam, LPARAM lParam)
{
POSITION pos = GetFirstViewPosition();
while (pos != NULL)
{
CView* pView = GetNextView(pos);
pView->PostMessage(msg, wParam, lParam);
}
}
I hope this helps!
I had a similar problem however I found this provided answer to be insufficient as there are two parts to a solution to this question.
The first is as provided with the process of iterating through the various views and using PostMessage() to send a message to each view.
The second part is what to do on the CView side that is receiving the message being sent and I want to provide a bit of a note on that part.
In the MFC application I am working on, I wanted to send a message to the CView and was running into an exception due to a mistake on my part as to how to process the message being sent.
In the class derived from CDocument I had a function that iterates over the list of CView objects to send a message to each. In this particular case I was wanting to reposition the view port to a designated section of a report. This required the Windows message that was sent to include an offset value as well as a message identifier.
POSITION pos = GetFirstViewPosition();
while (pos != NULL)
{
CView* pView = GetNextView(pos);
if (pView)
pView->PostMessage(WM_APP + 10, sectionHeader.m_ListOffset, 1);
}
I am using the standard Windows SDK define WM_APP to create a unique message identifier within the range of user defined message ids (as opposed to standard Windows message ids) to send a message indicating the offset to use as the WPARAM argument of PostMessage(). See Message Map Macros - ON_MESSAGE which states:
User-defined messages are any messages that are not standard Windows
WM_MESSAGE messages. When selecting a message ID, you must use values
within the range of WM_USER (0x0400) to 0x7FFF or WM_APP (0x8000) to
0xBFFF. For more information regarding message IDs, see WM_APP.
In the CView class I added an entry to the message map for the CView class. I am using ON_MESSAGE rather than ON_COMMAND because I need to provide the offset to the CView processing the message.
ON_MESSAGE(WM_APP + 10, &CPCSampleView::OnWindowSetSection)
and then added the source for the actual message handler itself which calculates the correct viewport scroll position by using the offset of the text line in a buffer along with the line height of each text line:
LRESULT CPCSampleView::OnWindowSetSection(WPARAM wParam, LPARAM lParam)
{
CPCSampleDoc *pDoc = GetDocument();
CPoint ptOrigin;
ptOrigin = GetScrollPosition();
wParam *= m_sizeCell.cy; // multiple text line offset by height of each line of text
ptOrigin.y = wParam; // change the vertical position of the scroll bar
ScrollToPosition(ptOrigin); // move the scroll bar elevator
this->UpdateWindow(); // tell view to update displayed window to match elevator position
return 0;
}
For more details about messages see Message Handling and Mapping in the Microsoft docs.
I have a property sheet that I have created and each of the tab pages share the same pfnDlgProc. In the pfnDlgProc, I have this code:
switch (msg) {
case WM_NOTIFY:
nmhdr = (NMHDR*)lParam;
switch (nmhdr->code) {
case PSN_QUERYCANCEL:
printf("PSN_QUERYCANCEL\n");
SetWindowLong(nmhdr->hwndFrom, DWL_MSGRESULT, FALSE);
return TRUE;
}
break;
...
}
When I click the Cancel button on my property sheet, PSN_QUERYCANCEL is printed, but the property sheet does not close. Why is this? Is there something else I need to do to allow it to/make it close? I know I can add DestroyWindow(nmhdr->hwndFrom) to the handler but is that the proper way to do it?
You are setting the DWL_MSGRESULT on the window handle that sent you the notification, but not necessarily the window that is the dialog you are processing the WM_NOTIFY for. Instead of using the nmhdr->hwndFrom window handle, try using the HWND that is passed to your pfnDlgProc.
In Windows application, is it possible to show a popup message in front of SaveAs dialog after SaveAs dialog is being opened? All I managed to get is that popup shows after dialog is closed.
I need to edit an old application written in C++ (I am not author) but can't manage this task. This is part of code:
/* ---- called to display the save file dialog ---- */
ofn.hwndOwner = hwnd;
ofn.lpstrFile = lpstrFileName;
ofn.lpstrTitle = lpstrTitleName;
res = GetSaveFileNameW( &ofn );
/* ---- fix file extension ---- */
MessageBox(NULL, "Test", "Testing", MB_OK);
Thanks,
Ilija
If I understand you correct, you want check some stuff (for example, file extension) before closing dialog and show message withou closing. If it's so please look at OFN_ENABLEHOOK flag in OPENFILENAME Structure. In this case your code will look something like
ofn.hwndOwner = hwnd;
ofn.lpstrFile = lpstrFileName;
ofn.lpstrTitle = lpstrTitleName;
/* enables the hook function */
ofn.Flags |= OFN_ENABLEHOOK;
ofn.ofn.lpfnHook = (LPOFNHOOKPROC) MyHookProc;
/* some code here */
res = GetSaveFileNameW( &ofn );
Code for MyHookProc will look like this:
static UINT CALLBACK MyHookProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_NOTIFY) {
OFNOTIFYW *notify = (OFNOTIFYW *) lParam;
if (notify->hdr.code == CDN_FILEOK) {
/* your code here */
}
}
}
Hope it will be helpful for you.
You can but it would be quite a hack. You would have to create the FileDialog and open it modeless rather than modal, and hidden. So the window is there but you can't see it. When you click your "popup" you can then could unhide the windows dialog.
It sounds like you want to extend the GUI of a save file dialog box. You can extend the GUI by using your own dialog resource template, and specify OFN_ENABLETEMPLATE. This is how many apps show previews / metadata of documents.