I have an MFC dialog with a button and a Picture control. When I click the button, I draw line inside the picture control.
The problem is that the CDC I get is the whole dialog client area. So the line is drawn outside the picture control. I need to get the CDC of only the Picture control, because the line coordinates should be relative to picture control rectangle.
Here is the code:
void SimulatorDlg::OnBnClicked()
{
CDC *pDC = GetDlgItem(IDC_VIDEO_PREVIEW)->GetDC();
pDC->MoveTo(0,0);
pDC->LineTo(100,100);
ReleaseDC(pDC);
}
IDC_VIDEO_PREVIEW is the id of the Picture Control, which is inside the dialog.
Related
This application creates a child window (which is the white box) when I right click anywhere, and destroys the child window after another right click. I have implemented the mechanics to expand and shrink the red rectangle through Direct 2D. I would like the child window to display the width and height of the rectangle at real time, as I make changes to it. I do not interact with the child window at all: it doesn't need an "x" button for closing and stuff; it just prints out a couple lines of data.
Here is what I have in my main window procedure:
case WM_RBUTTONUP:
{
DemoApp *pDemoApp = reinterpret_cast<DemoApp *>(static_cast<LONG_PTR>(
::GetWindowLongPtrW(hwnd, GWLP_USERDATA)));
pDemoApp->showTextBox = !pDemoApp->showTextBox; //showTextBox is a boolean
if (pDemoApp->showTextBox) {
POINTS cursor = MAKEPOINTS(lParam);
pDemoApp->child_hwnd = CreateWindowEx(
WS_EX_TOPMOST,
"LISTBOX",
"I dont need a title here",
WS_CHILDWINDOW,
cursor.x,
cursor.y,
100,
200,
pDemoApp->main_hwnd,
NULL,
HINST_THISCOMPONENT,
pDemoApp
);
ShowWindow(pDemoApp->child_hwnd, SW_SHOWNORMAL);
UpdateWindow(pDemoApp->child_hwnd);
}
else {
DestroyWindow(pDemoApp->child_hwnd);
}
}
break;
How may I go from here? I would like to know:
Is using Direct Write to draw text in the child window my only option? I see the dashed lines in the white box so I assume there must be a way to display plain text.
I used LISTBOX here, which is a predefined windows class name. How do I set a procedure for it? What else predefined class name can better suit my need? Or do I have to register a custom one;
I would like to drag the child window around, how can I set it up so that the system handles dragging for me.
Would popping a dialog box to display text be better than popping a child window?
Thanks.
Since you are using a Win32 LISTBOX control as the child window, then you have a couple of options for displaying the rectangle's dimensions in it:
give the ListBox the LBS_HASSTRINGS style, and add 1-2 items to it. Then, any time you change the rectangle, send LB_DELETESTRING and LB_ADDSTRING messages to the ListBox's HWND to display the updated dimensions as needed. A ListBox does not have a way to update an existing item, so to change an existing item's text, you have to remove the item and then re-add it with the new text.
give the ListBox an LBS_OWNERDRAW... style, and add 1-2 blank item(s) in it. Then have the ListBox's parent window handle WM_MEASUREITEM and WM_DRAWITEM notifications from the ListBox to display the rectangle's current dimensions in the item(s) as needed. Whenever the rectangle is changed, call InvalidateRect() on the ListBox's HWND to trigger a redraw.
I'm currently trying to build a player literally from scratch using Media Foundation Interfaces.
I use the example taken from here:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd979592(v=vs.85).aspx
As the basis for the player.
I want to add buttons (back/forward button , progress bar etc.) to the video screen window, but it isn't so clear to me how.
I can not simply add a button as a child of the main window because it is hidden by the player, I tried to add the buttons as children of Video window but it did not work ...
What is the right way to add buttons to a video window?
This is part of the code where you register to the player window (to the full code please enter the link I have attached).
// create the instance of the player hwnd = handle of main window
HRESULT hr = CPlayer::CreateInstance(hwnd, hwnd, &g_pPlayer);
// inner call to cplayer
CPlayer *pPlayer = new (std::nothrow) CPlayer(hVideo, hEvent);
// Create a partial topology. (m_hwndVideo == hVideo == hwnd)
hr = CreatePlaybackTopology(m_pSource, pSourcePD, m_hwndVideo, &pTopology);
i try to use this function in order to change video paint so i will have some
place left at the bottom to put there my buttons, here is my function:
VOID update_lower_window(HWND hwnd)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
RECT rc;
GetClientRect(hwnd, &rc);
//rc = father size
RECT repaint;
memcpy(&repaint, &rc, sizeof(RECT));
repaint.top = repaint.bottom - DOWN_SPACE; // DOWN_SPACE == 50
// paint back bottom to white
FillRect(hdc, &repaint, (HBRUSH)COLOR_WINDOW);
EndPaint(hwnd, &ps);
}
i call this function when:
WM_PAINT happend
WM_SIZE happend
WM_CREATE happend
With this said I still could not achieve my goals:
When the movie starts playing it starts full screen and does not leave the space I wanted down (I can not seem to find the message sent when the movie is played or in other words when the movie paint on the screen it's not sent one of the messages on which I inserted my function)
When I reduce the screen, the remnants of the previous screen still remain down and I can't see the background.
When using the Minimize button it get the same phenomenon as in 2.
Another interesting detail The phenomenon I mentioned in 2 occurs only when I change window size by drag from the bottom up, if I change window size by drag from one corner (enlarges or decreases height and width simultaneously) then the window corrects itself and I see in the bottom white part (the background) all the time.
You can reposition video area so your win32 GUI (buttons and progress) is below. See WM_SIZE handler in that sample for how to do it, they calculate rectangle to occupy the window, you can adjust to accommodate your controls.
If you want translucent overlaid controls you can write a EVR Presenter.
https://msdn.microsoft.com/en-us/library/windows/desktop/bb530107(v=vs.85).aspx
https://github.com/Microsoft/Windows-classic-samples/tree/master/Samples/Win7Samples/multimedia/mediafoundation/evrpresenter
But that’s relatively hard.
P.S. If you just want a simple solution, use something higher-level. Like Windows Media Player control note they have a C++ example, or .NET for GUI and MediaElement in it.
Update: I think the right place to set initial video position in that sample is likely CPlayer::OnTopologyStatus, after MFGetService(MR_VIDEO_RENDER_SERVICE) line.
Anyway, another approach that might be simpler for your task, create a child window dedicated to the video. Position it so it occupies the majority of your app’s main window, and only leaves bottom 50px unoccupied. Don’t forget to handle at least WM_SIZE to reposition and ideally also WM_DISPLAYCHANGED, WM_ENDSESSION, WM_GETMINMAXINFO. Setup the MF playback so that video occupies the complete child video window.
This will ensure the video won’t interfere with Win32 stuff you’re painting on your bottom 50px panel.
BTW that’s what MPC-HC is doing, see the pic.
As you see on Spy++ screenshot, they have dedicated video window, and also other child windows for Win32 controls of the player.
I am creating some dialog-based MFC application (C++) and need to use tab control. Here is the code where I try to adjust child dialog to a tab control display area (Visual Studio 2015):
/* main dialog */
BOOL CResourceBrowserDlg::OnInitDialog()
{
....
/*
* `m_Page` is my child dialog instance:
* CDlgFilterPage::CDialogEx *m_Page
*/
m_Page = new CDlgFilterPage();
m_Page->Create(IDD_FILTERPAGE, m_FilterTab.GetWindow(IDD_FILTERPAGE));
RECT rect;
/*
* `m_FilterTab` is a tab control element:
* CTabCtrl m_FilterTab
*/
m_FilterTab.GetWindowRect(&rect);
m_FilterTab.AdjustRect(FALSE, &rect);
m_Page->MoveWindow(&rect);
m_Page->ShowWindow(SW_SHOW);
m_FilterTab.InsertItem(0, L"Page1");
...
}
Running this i got the following:
So how should I act to get child window fit nicely within tab control?
First of all, you probably want to first add a page and then position the other dialog within the client area of the tab. Otherwise, your tab window will not have the tab buttons and the size of the dialog will be larger than what you expect.
Second, you need to position the new dialog inside the client area. You have to retrieve that and then translate it based on the window area.
Here is how you do all that:
m_Page = new CDlgFilterPage();
m_Page->Create(IDD_FILTERPAGE, m_FilterTab.GetWindow(IDD_FILTERPAGE));
m_FilterTab.InsertItem(0, L"Page1");
CRect rcClient, rcWindow;
m_FilterTab.GetClientRect(&rcClient);
m_FilterTab.AdjustRect(FALSE, &rcClient);
m_FilterTab.GetWindowRect(&rcWindow);
ScreenToClient(rcWindow);
rcClient.OffsetRect(rcWindow.left, rcWindow.top);
m_Page->MoveWindow(&rcClient);
m_Page->ShowWindow(SW_SHOW);
The result is this:
Do not try to get the Window position in OninitDialog() function. It will show 0,0 location instead of actual position of dialog.
I have a child window derived from CMDIChildWndEx named as CTestTooltipMdiChildWnd, on CTestTooltipMdiChildWnd titlebar, I have drawn a custom icon which is initially disabled.
When user mouse over on this custom icon, I should get a tooltip displayed.
I get rect value of custom icon.
Any input how can I do this.Can anybody suggest any link where tutorial is available to understand.
I am trying to intercept the WM_NCPAINT message by first calling ::DefWindowProc, then paint over it. However, when I paint the window controls of the title bar or non-client area, I need to have its RECT structure. Therefore, how do I access the REcT structure?
The update region is passed in message's wParam. The non client area of the window isn't rectangular so you don't get a single RECT.
I presume you are aware that WM_
NCPAINT is not compatible with Vista DWM glass.