Im working on some Window Customizing stuff.
I removed title bar and border of CFrameWnd and added my own title bar.
It seems work nice.
But if I add menu to this window, menu will be on top of this window. (above my title bar)
So I add new CFrameWnd and set my menu to this new CFrameWnd.
this is the code.
CMenu * pMenu = this->GetMenu();
if( pMenu != NULL )
{
this->SetMenu(NULL);
m_pMenuWnd = new CMenuWindow();
m_pMenuWnd->Create(NULL, NULL, 0, m_WindowRects.MenuRect, this, 0, NULL);
m_pMenuWnd->SetMenu(pMenu);
m_pMenuWnd->ShowWindow(SW_NORMAL);
}
And I added this menu window's move handler on my custom CFrameWnd's OnSize, OnMove Message Handler for corrent positionning.
It looks pretty good.
But when I minimize and restore its position, menu windows position is just white blank.
But if I move cursor on there, menus r there.
What am I doing wrong?
I checked OnCtlColor but its not even get called.
Here's CMenuWindow code
BEGIN_MESSAGE_MAP(CMenuWindow, CFrameWnd)
ON_WM_CREATE()
ON_WM_ACTIVATE()
ON_WM_KEYUP()
ON_WM_SYSKEYUP()
END_MESSAGE_MAP()
void CMenuWindow::OnDraw(CDC* pDC)
{
CRect clRect;
GetClientRect(&clRect);
}
// CMenuView message handlers
int CMenuWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
ModifyStyle(WS_CAPTION, WS_CLIPCHILDREN);
ModifyStyleEx(WS_EX_CLIENTEDGE,0);
return 0;
}
Related
I've got a "default looking" dialog box like the following:
And I'm attempting to modify the tabs and insert a RichEditCtrl in the first tab.
InitCommonControlsEx;
CWnd* pTab = GetDlgItem(IDC_TAB1);
if (pTab) {
CRect rect;
m_TabCtrl = (CTabCtrl*)pTab;
m_TabCtrl->GetClientRect(&rect);
m_TabCtrl->InsertItem(0, "Stats");
m_TabCtrl->InsertItem(1, "Settings");
BOOL getRect = m_TabCtrl->GetItemRect(0, &rect);
if (!m_richEditCtrl.Create(WS_VISIBLE | ES_READONLY | ES_MULTILINE | ES_AUTOHSCROLL | WS_HSCROLL | ES_AUTOVSCROLL | WS_VSCROLL, rect, m_TabCtrl, 0))
return FALSE;
m_font.CreateFont(-11, 0, 0, 0, FW_REGULAR, 0, 0, 0, BALTIC_CHARSET, 0, 0, 0, 0, "Courier New");
m_richEditCtrl.SetFont(&m_font);
}
The sample I'm modifying previously had only used the RichTextCtrl and "created" it inside of a "placeholder" text box. It worked great, but I wanted to shove that RichTextCtrl into a tab, and create another tab to display some data. The problem is that I now just get 2 blank tabs. I know that the parent dialog settings "Clip Children" and "Clip Siblings" may matter, but I'm not sure which if I need, if either. I also know that my RichEditCtrl still exists because I'm still sending data to it, but it's certainly not displaying.
This piece of my program isn't even really that urgent, and I am just trying to get this to work on principal at this point...
Tab Controls create the illusion, that the dividers and the display area were part of the same control. That's not the case. The tab control is really just the labels, plus the placeholder display area. Bringing the display area's contents to live is the responsibility of the application.
In general, the following steps are required to implement a fully functional tab control:
Create the tab control plus labels.
Create the display area's child controls. It is common to place the controls comprising a single "page" in a dialog.
Subscribe to the TCN_SELCHANGE message, and dynamically update the visibility of the controls, i.e. hide all controls that aren't part of the current "page" and show all controls that are. Placing all controls for a "page" inside a dialog makes this easier by only requiring to toggle the visibility of the dialogs.
This is a rough overview of how tab controls work. Given your code, there are some things you need to change. Specifically, the following need to be taken care of:
The tab control referenced by IDC_TAB1 needs to have the WS_CLIPCHILDREN style, so that the display area doesn't cover the child controls.
m_richEditCtrl needs to be created with the WS_CHILD style.
Calculate the size of the display area using CTabCtrl::AdjustRect and use that to size the m_richEditCtrl to fill the entire display area (if that is what you want).
With those changes you should see a tab control whose display area is filled by a Rich Edit control. Switching between tabs doesn't change the contents of the display area just yet. That's something you'll need to implement as required by your application.
The following code sample is based on a wizard-generated dialog-based application named MfcTabCtrl. The generated dialog resource (IDD_MFCTABCTRL_DIALOG) had all content removed, leaving just a blank dialog template.
Likewise, the main dialog implementation had most of its functionality stripped, leaving just the vital parts. This is the MfcTabCtrlDlg.h header:
#pragma once
#include "afxdialogex.h"
// Control identifiers
UINT constexpr IDC_TAB{ 100 };
UINT constexpr IDC_RICH_EDIT{ 101 };
class CMfcTabCtrlDlg : public CDialogEx
{
public:
CMfcTabCtrlDlg(CWnd* pParent = nullptr);
protected:
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnTabChanged(NMHDR* pNMHDR, LRESULT* pResult);
// Convenience implementation to calculate the display area
RECT GetDisplayArea();
virtual BOOL OnInitDialog();
DECLARE_MESSAGE_MAP()
private:
CTabCtrl m_TabCtrl{};
CRichEditCtrl m_richEditCtrl{};
};
The implementation file MfcTabCtrlDlg.cpp isn't very extensive either:
#include "MfcTabCtrlDlg.h"
CMfcTabCtrlDlg::CMfcTabCtrlDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_MFCTABCTRL_DIALOG, pParent)
{
}
void CMfcTabCtrlDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
// Resize tab control only after it has been created
if (IsWindow(m_TabCtrl)) {
m_TabCtrl.MoveWindow(0, 0, cx, cy);
// Determine display area
auto const disp_area{GetDisplayArea()};
// Resize child control(s) to cover entire display area
if (!IsRectEmpty(&disp_area) && IsWindow(m_richEditCtrl)) {
m_richEditCtrl.MoveWindow(&disp_area);
}
};
}
void CMfcTabCtrlDlg::OnTabChanged(NMHDR* /*pNMHDR*/, LRESULT* pResult)
{
auto const cur_sel{ m_TabCtrl.GetCurSel() };
switch (cur_sel) {
// First tab selected
case 0:
m_richEditCtrl.ShowWindow(SW_SHOW);
break;
// Second tab selected
case 1:
m_richEditCtrl.ShowWindow(SW_HIDE);
break;
}
// Allow other subscribers to handle this message
*pResult = FALSE;
}
// Returns the display area in client coordinates relative to the dialog.
// Returns an empty rectangle on failure.
RECT CMfcTabCtrlDlg::GetDisplayArea()
{
RECT disp_area{};
if (IsWindow(m_TabCtrl)) {
m_TabCtrl.GetWindowRect(&disp_area);
m_TabCtrl.AdjustRect(FALSE, &disp_area);
this->ScreenToClient(&disp_area);
}
return disp_area;
}
// The message map registers only required messages
BEGIN_MESSAGE_MAP(CMfcTabCtrlDlg, CDialogEx)
ON_WM_SIZE()
ON_NOTIFY(TCN_SELCHANGE, IDC_TAB, &CMfcTabCtrlDlg::OnTabChanged)
END_MESSAGE_MAP()
BOOL CMfcTabCtrlDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// Set up tab control to cover entire client area
RECT client{};
GetClientRect(&client);
m_TabCtrl.Create(WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN, client, this, IDC_TAB);
m_TabCtrl.InsertItem(0, L"Stats");
m_TabCtrl.InsertItem(1, L"Settings");
// Set up rich edit control.
// The WS_BORDER style is set strictly to make it visible.
auto const disp_area{ GetDisplayArea() };
m_richEditCtrl.Create(WS_BORDER | WS_VISIBLE | WS_CHILD,
disp_area, &m_TabCtrl, IDC_RICH_EDIT);
return TRUE; // Let the system manage focus for this dialog
}
The result is a dialog holding a tab control with two labels. Visibility of the contained rich edit control is toggled in the TCN_SELCHANGE notification handler, showing it only when the first tab is selected. A more complex GUI would update the visibility of all controls based on the currently selected tab here as well.
Note that the controls inside the tab control's display area are never destroyed during the dialog's life time. This is usually desirable to persist user data even when switching between tabs. If necessary it is also possible to destroy and (re-)create some or all of the child controls when switching tabs.
Output is show in picture
I am using one CStatic control with variable as "m_background" and ID as IDC_background. In this control, the video has been run on the click of the button. and there is second control Edit Control with variable as "m_edit" and ID as IDC_edit.This Edit Box is placed over static control. I want to show the text written in Edit Control on video while we play video on click of the button with transparent background color of EDit Control.
But the problem is grey/white background has appeared for m_edit control while we play video. I want to show the text on the video with transparent background of the "m_edit" control while we play the video.
BOOL CtestcodeDlg::OnInitDialog()//To set up the video in background and text above the video
{
m_background.ModifyStyle(0, WS_CLIPSIBLINGS);
m_edit.SetWindowPos(&CWnd::wndTop, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE|WS_EX_TRANSPARENT);
return TRUE; // return TRUE unless you set the focus to a control
}
HBRUSH CtestcodeDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) //To transparent the background of Edit box
{
HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
HBRUSH m_default=CreateSolidBrush(RGB(0,0, 0));
if(pWnd->GetDlgCtrlID() == IDC_edit)
{
pDC->SetTextColor(RGB(255,0,0));
pDC->SetBkColor(TRANSPARENT);
pDC->SetBkMode(TRANSPARENT);
}
return hbr;
}
void CtestcodeDlg::OnBnClickedButton1()////To run the video
{
my_instance = libvlc_new(0, NULL);
my_media_file = libvlc_media_new_location(my_instance,
"rtsp://BigBuckBunny_115k.mov");
my_player = libvlc_media_player_new_from_media(my_media_file);
my_event_manager = libvlc_media_player_event_manager(my_player);
libvlc_media_player_play(my_player);
libvlc_audio_set_track(my_player ,-1);
libvlc_media_player_set_hwnd(my_player, m_background);
Sleep(1000);
_beginthread(test, 0, NULL);
libvlc_audio_set_track(my_player ,-1);
}
Try using SetLayeredWindowAttributes function, with the crKey of your bk color.
Also, i think pDC->SetBkColor(TRANSPARENT); in your code is a mistake, it sets bk color to black. Try to run without this call.
I created a MFC application.Sometimes the controls(Button,Label etc) in the Dialog goes invisible at run time.The Dialog form remains.This is a random issue.The screenshots of the dialog in normal time and when goes blank are attached.Can anyone help me to find the solution for this ?
http://i.stack.imgur.com/KTDGV.png
http://i.stack.imgur.com/3PqUb.png
for displaying/hiding the Dialog i used the following code
void CVideoConverter::PopUpDlg(BOOL bValue)
{
try
{
if(bValue) // show
{
CVideoConverterApp::m_pCVideoConverterDlg->ShowWindow(SW_SHOWNORMAL);
CVideoConverterApp::m_pCVideoConverterDlg->UpdateWindow();
}
else
{// hide
CVideoConverterApp::m_pCVideoConverterDlg->ShowWindow(SW_MINIMIZE);
}
}
catch(...)
{}
}
The following code was used to position the dialog to bottom right corner of the window.This is called before the PopupDlg()
void CVideoConverter::SetWindowToBottomRightCorner()
{
try
{
CRect rcScreen;
SystemParametersInfo(SPI_GETWORKAREA, 0, (void *) &rcScreen, 0);
CRect rcWindow;
GetWindowRect(&rcWindow);
MoveWindow(rcScreen.right - rcWindow.Width(), rcScreen.bottom - rcWindow.Height(), rcWindow.Width(), rcWindow.Height(), TRUE);
}
catch(...)
{}
}
I have a modal dialog with a list control. Right clicking one of the items in the list control, shows a content menu. Clicking this popup menu, opens another modal dialog with another list control.
My problem is that I can't display a right click content menu for the list control in the second dialog.
I tried:
void CMyListCtrl::OnContextMenu(CWnd* , CPoint point)
{
if (GetSelectedCount() == 0)
return ;
if (point.x == -1 && point.y == -1)
{
//keystroke invocation
CRect rect;
GetClientRect(rect);
ClientToScreen(rect);
point = rect.TopLeft();
point.Offset(5, 5);
}
CMenu menu;
VERIFY(menu.LoadMenu(IDR_HISTORY_MENU));
CMenu* pPopup = menu.GetSubMenu(0);
ASSERT(pPopup != NULL);
CWnd* pWndPopupOwner = this->GetParent();
SetForegroundWindow();
pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
point.x,
point.y,
pWndPopupOwner);
}
and I also added to the parent dialog ON_WM_INITMENUPOPUP
Also tried just to create a popup menu on the fly
void CHistoryListCtrl::OnContextMenu(CWnd* , CPoint point)
{
if (GetSelectedCount() == 0)
return ;
if (point.x == -1 && point.y == -1)
{
//keystroke invocation
CRect rect;
GetClientRect(rect);
ClientToScreen(rect);
point = rect.TopLeft();
point.Offset(5, 5);
}
CMenu addMenu;
addMenu.CreatePopupMenu();
// add all possible interface items
CString mstr; mstr="Compare";
addMenu.AppendMenu(MF_ENABLED | MF_STRING,ID_HISTORY_COMPARE , (LPCTSTR)mstr);
addMenu.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON,point.x,point.y,this,NULL);
addMenu.DestroyMenu();
}
It didn't work as well. Tried to add SetForgroundWindow before the call to TrackPopupMenu, but it also failed.
Any idea what to do ?
I am trying to add to CSliderCtrl in CStatusBar. For this
- Created CSliderCtrl in CMainFrame class
- In CMainFrame::OnCreate() added code for creating statusbar and slider bar control as
bStatus = m_ZoomSlider.Create(
WS_CHILD | WS_VISIBLE,
CRect(0, 0, 100, 30),
&m_StatusBar,
56666);
Things are working fine.
Now I want this slider to be on the right side of the status bar. For this I've added a INDICATOR in the status bar and I am trying to get the rect of this indicator and placing the slider over that rect.
CRect rectSlider;
m_StatusBar.GetItemRect(1, &rectSlider);
bStatus = m_ZoomSlider.Create(
WS_CHILD | WS_VISIBLE,
rectSlider,
&m_StatusBar,
56666);
Here the rectSlider is having negative value, causing the slider to be invisible.
I need to know Is this the correct way for doing this. Any suggestion for advice will be very helpful.
I am using Visual Studio 2005.
You should be using GetRect rather than GetItemRect, I think
The slider control cannot be displayed because its Z-order is not correct. So override on resize to reposition the slider properly. &CWnd::wndTop means placing the window at the top of the Z-order
Firstly, define CSliderCtrl *m_pZoomSlider in MainFrame.h
The following code used the lazy initialization pattern: initialize when required, free the allocated memory when frame is being destroyed.
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
...
ON_WM_SIZE()
END_MESSAGE_MAP()
void CMainFrame::SetSliderPosition(int pos)
{
if (!m_pZoomSlider) {
CRect rectSlider;
m_wndStatusBar.GetItemRect(1, &rectSlider);
rectSlider.DeflateRect(1, 1); // 1 pixel border...
m_pZoomSlider = new CSliderCtrl();
m_pZoomSlider->Create(WS_CHILD | WS_VISIBLE, rectSlider, &m_wndStatusBar, ID_INDICATOR_SCALE_SLIDER);
m_pZoomSlider->SetRange(1, 100);
}
RECT rc;
m_wndStatusBar.GetItemRect(pos, &rc);
// Reposition the slider control correctly!
m_pZoomSlider->SetWindowPos(&CWnd::wndTop, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, 0);
}
void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
CFrameWnd::OnSize(nType, cx, cy);
SetSliderPosition(1); //index of indicator of status bar
}
BOOL CMainFrame::DestroyWindow()
{
if (m_pZoomSlider) {
m_pZoomSlider->DestroyWindow();
delete m_pZoomSlider;
}
return CFrameWnd::DestroyWindow();
}