ActiveX HWND, DirectX WindowLess mode - c++

I would like to render video in ActiveX control (not in pop-up DirectShow window). I have:
IID_IVMRWindowlessControl
IID_IVMRFilterConfig9
CLSID_VideoMixingRenderer9
I would like to set WindowLess mode, but I don't know how to get HWND of..., exactly, of what? IEFrame, HTML element?
hr = pWc->SetVideoClippingWindow(???);
Anyone with some hint?
Regards.

First of all, add this to the constructor of your ActiveX control:
// this seemingly innocent line is _extremely_ important.
// This causes the window for the control to be created
// otherwise, you won't get an hWnd to render to!
m_bWindowOnly = true;
Your ActiveX control will have a member variable called m_hWnd that you'll be able to use as a render target. without the m_bWindowOnly variable set true, the ActiveX control won't create its own window.
Finally, pick your renderer (VMR9 for example)
CRect rcClient;
CComPtr<IBaseFilter> spRenderer;
CComPtr<IVMRWindowlessControl9> spWindowless;
// Get the client window size
::GetClientRect(m_hWnd, rcClient);
// Get the renderer filter
spRenderer.Attach( m_pGraph->GetVideoRenderer() );
if( ! spRenderer )
return E_POINTER;
spWindowless = spRenderer;
if( spWindowless )
{
spWindowless->SetVideoClippingWindow( m_hWnd );
spWindowless->SetVideoPosition(NULL, rcClient);
spWindowless.Release();
}
spRenderer.Detach();
Please note that my graph object is a custom object and that GetVideoRenderer() is one of my own functions - it returns an IBaseFilter*.
It took me ages to find this one out. ATL is poorly documented, which is a shame, because it's an excellent technology. Anyways, hope this helps!

freefallr's info is extremely helpful, but I don't think it answers your question completely. The trick with windowless activex controls is that you don't get a window. When you draw you'll just basically get a device context and you have to respond to call from the browser and only draw when it tells you to.
The interfaces required are here: http://msdn.microsoft.com/en-us/library/ms682300%28v=VS.85%29.aspx
more info here: http://msdn.microsoft.com/en-us/library/aa751970%28VS.85%29.aspx#OC96_and_Windowless_
We've been meaning to add support for this in FireBreath (http://firebreath.org) for awhile; we have support for it in all npapi browsers, but looks like we don't (yet) support IE. If you find more details, post a summary here =]

Related

C++ Set window below (or above) the icons on the desktop

I'm trying to place a window either above or below the icons on the desktop. I mostly just want it to stay attached to the desktop at all times. Similar to Rainmeter or Wallpaper engine. So far, everything I tried either disables interaction, or gets minimized when you use the "Show Desktop" button. Any ideas on how to achieve this? I'm using electron and a native module in node to do this.
It's an old subject, but I'll find out how to do it recently and answer it.
The method is to find the handle of SHELLDLL_DefView, the parent of the desktop window, and then make the SHELLDLL_DefView handle the parent of my window to fix it to the desktop.
The method is to find the handle of SHELLDLL_DefView, the owner of the desktop window, and then make the SHELLDLL_DefView handle the owner of my window to fix it to the desktop.
SHELLDLL_DefView is located under the Progma or WorkerW handle. This is a code to prevent ShowDesktop from being used in the Electget package created by ffi-napi to attach the Electron browserWindow to the desktop.
const GWLP_HWNDPARENT = -8;
// find SHELLDLL_DefView in Progma
const progman = user32.FindWindowExA(ref.NULL, ref.NULL, 'Progman', ref.NULL);
let defView = user32.FindWindowExA(progman, ref.NULL, 'SHELLDLL_DefView', ref.NULL );
// find SHELLDLL_DefView in WorkerW
if (!defView) {
const desktopHWnd = user32.GetDesktopWindow();
let workerW = 0;
do {
workerW = user32.FindWindowExA(desktopHWnd, workerW, 'WorkerW', ref.NULL);
defView = user32.FindWindowExA(workerW, ref.NULL, 'SHELLDLL_DefView', ref.NULL );
} while (!defView && workerW);
}
if (!defView) return false;
// make the SHELLDLL_DefView handle the parent of my window
user32.SetWindowLongPtrA(hWnd, GWLP_HWNDPARENT, defView);
This allows you to create a window where you can click and interact without being hidden by ShowDesktop.
2022-03-29
There was a wrong word, so I corrected it. According to doc, it is not a parent window, but an owner window. In the doc, it is strange that the GWLP_HWNDPARENT constant is related to the parent window. However, when tested with Spy++, the corresponding constant changes the owner window.

Is there a way to get IShellBrowser from a dialog?

I know that windows common dialog have a IShellBrowser interface and its class name is 'SHELLDLL_DefView'. Refer this.
How to get the IShellBrowser interface of a file open dialog?
(The file open dialog is outside's, not my application's.)
This is the same as my question but is delphi(?) ver.
I don't know delphi code. How to solve this problem as C++ or MFC code?
Here is a C/C++ translation of the Delphi code:
const UINT CWM_GETISHELLBROWSER = WM_USER + 7;
IShellBrowser *ShellBrowser = (IShellBrowser*) SendMessage(aDialog, CWM_GETISHELLBROWSER, 0, 0);
if (ShellBrowser) {
ShellBrowser->AddRef();
// use ShellBrowser as needed...
ShellBrowser->Release();
}
You might also want to read the following article, which provides a slightly more official (ie, more reliable, but more complicated) way to get an IShellBrowser for a given HWND:
Querying information from an Explorer window
Start with the ShellWindows object which represents all the open shell windows. You can enumerate through them all with the Item property... From each item, we can ask it for its window handle and see if it's the one we want... Okay, now that we have found the folder via its IWebBrowserApp, we need to get to the top shell browser. This is done by querying for the SID_STopLevelBrowser service and asking for the IShellBrowser interface.

How to use a custom cursor?

I'm trying to change the default OS cursor to a custom one. As of now, I'm only dealing with Windows. I got an image file with the cursor I want (.png, should I change format?).
All in all, I've been searching and trying to simply change the cursor, with no success.
Also, as of now I'm looking for the most simple solution, with as few line of codes as possible.
If relevant:
-I'm using a window created with SFML(2.1).
-The following compiles but makes no difference:
HCURSOR hCursor = LoadCursor(NULL, "path/filename.png");
SetCursor(hCursor);
So, I'm seeking the knowledge of the community, any ideas?
The following works :)
It does however immediately revert back to default windows mouse:
HCURSOR hCursor = LoadCursorFromFile("path/filename.cur");
SetCursor(hCursor);
I found this LINK, which seems to be the same problem as mine.
I am however unable to apply the answer given in the link
HWND windowHandle;
int GCL_Hcursor = -12; //GCL_HCURSOR
HCURSOR hCursor = LoadCursorFromFile("Graphics/Cursors/Pointer_small.cur");
SetCursor(hCursor);
SetClassLong(windowHandle, GCL_Hcursor, (DWORD)hCursor);
I (obviously?) get:
uninitialized local variable 'windowHandle' used
After roughly 4 hours and 30 minutes trying to get a custom mouse working with SFML on Windows, I finally managed to accomplish a task for which I had expected to use no more than 5 to 10 minutes. As such, I leave here the answer to my very own question, since the internet was unable to provide it clean and clear to a noob like me. May it be useful to whoever may need it.
#include <SFML/Graphics.hpp>
#include <windows.h>
int main()
{
sf::RenderWindow window(sf::VideoMode(800, 600), "Simple Cursor Demonstration");
// {This is what matters}
{
sf::WindowHandle wHandle;
wHandle = window.getSystemHandle();
HCURSOR Cursor = LoadCursor(NULL, IDC_HAND); // IDC_ARROW IDC_WAIT IDC_HAND... http://msdn.microsoft.com/en-us/library/ms648391%28v=vs.85%29.aspx
//HCURSOR Cursor = LoadCursorFromFile("path/filename.cur"); //.cur or .ani
SetCursor(Cursor);
SetClassLongPtr(wHandle, GCLP_HCURSOR, reinterpret_cast<LONG_PTR>(Cursor));
}
// to prove it works, just move the mouse around
// not 100% sure the following actually proves it, but the above worked wonders on the project I wanted it for
window.clear(sf::Color(sf::Color(0, 255, 0)));
window.display();
sf::sleep(sf::milliseconds(3000));
return 0; //I've read this line or equivalent is a good idea... :)
}
Sources:
-This solution was plundered from around the internet, but mainly from Overcomplicated for a Noob ,which was also mentioned by someone who deleted their answer. While being [Overcomplicated for a Noob], it does seem to provide great information on how to properly implement custom cursors on a program, as well as how to do it on apple OS thingy instead
-This was also useful.
-colinsmith mentioned the cursor file must be .cur or .ani, .png does indeed not work
Creating a Cursor from a Bitmap is described here http://www.codeproject.com/Articles/5220/Creating-a-color-cursor-from-a-bitmap
Converting a png into a Bitmap can be done easily with CImage. Simply load the PNG and Detach the HBITMAP. But a Bitmap alone is no Cursor.
Cursors are set by the window that receive WM_SETCURSOR. So "replacing" a specific Cursor will not work. You have to intercept the WM_SETCURSOR message to change the cursor that should be returned.
Your Edit2 is wrong because you Need a valid window handle to change the cursor in the class of a window. But this will never work, ifthe window handles the Cursor by ist own (see 2)
PS: It would be better to inform yourself how Windows handles Cursors before you ask how to Change it globally...

Getting ActiveX window handle

I have followed this link to get the window handle of a ActiveX control
Sample Code from microsoft's site
// The following code should return the actual parent window of the ActiveX control.
HWND CMyOleControl::GetActualParent()
{
HWND hwndParent = 0;
// Get the window associated with the in-place site object,
// which is connected to this ActiveX control.
if (m_pInPlaceSite != NULL)
m_pInPlaceSite->GetWindow(&hwndParent);
return hwndParent; // Return the in-place site window handle.
}
But in my case I keep finding that "m_pInPlaceSite" is always NULL. I'm trying to run this code in my controls FinalConstruct. Is there something else I need to implement for the m_pInPlaceSite to be given a value? Or do I need to Query to get the value.
Thanks
FinalConstruct is way too early. In FinalConstruct your class is just being created and is not yet initialized. There is no "in place" site, there is no yet site at all.
Your control will be called by its owner, it will be given its site, then activated - only then you will possibly have m_pInPlaceSite available.

How to autodetect urls in RichEdit 2.0?

When we have a RichEdit control and send it an EM_AUTOURLDETECT message with WPARAM set to TRUE, it nicely hightlights the detected URLs and sends the EN_LINK notifications.
But it does this only for text that is entered into the control. I haven't found the way to do it for text that's loaded into the control with SetWindowText or EM_STREAMIN.
Please help! Thanks
Upd:
I've created a test application from scratch and it works fine there. I think the problem might be that I have superclassed the control, that is, created a new window class and just use the window procedure of the original class. I'm gonna try subclassing the control instead..
I just knocked up a basic WTL dialog based app containing a riched20 control and the following works fine:
CRichEditCtrl richedit = GetDlgItem(IDC_RICHEDIT);
richedit.SetAutoURLDetect(TRUE);
richedit.SetWindowText(_T("http://www.stackoverflow.com"));
I have some old MFC code that does something similar, albeit with ES_STREAM, and it works OK too.
FWIW the WTL CRichEditCtrl wrapper is pretty thin. SetAutoURLDetect simply calls SendMessage passing it EM_AUTOURLDETECT.
I am compiling with _RICHEDIT_VER set to 0x0200 FWIW.
Without knowing the format of the text you are trying to add to the control with SetWindowText and EM_STREAMIN I'm going to take a guess and say this might have something to do with the control's text mode. After setting the contents of the control try sending it a EM_GETTEXTMODE message and see if the TM_PLAINTEXT bit is set. If this is the case then try sending a EM_SETTEXTMODE message followed by EM_AUTOURLDETECT. Your code should look something like this:
UINT textmode = (UINT)::SendMessage(handle_to_control, EM_GETTEXTMODE, 0, 0);
if(textmode & TM_PLAINTEXT) {
textmode &= ~TM_PLAINTEXT; // Clear the TM_PLAINTEXT bit
textmode |= TM_RICHTEXT; // Set the TM_RICHTEXT bit
if(::SendMessage(handle_to_control, EM_SETTEXTMODE, textmode, 0) != 0) {
// Failed to set the text mode
}
}
::SendMessage(handle_to_control, EM_AUTOURLDETECT, TRUE, 0);
You might just have to rewrite the text to the control to get it to re-parse.