MFC Printing with CDC just works on some Printers - c++

I'm implementing a Printing Function in a big Project to print so called gadgets (derived from CWnd). In the Gadget Class I've created a Function to Render it to the Device Context
PrintPageContent(CDC * pDC, const CRect & rContent, int page, int numPages)
{
PrintWindow(pDC, PW_CLIENTONLY);
pDC->Rectangle(rContent.left,rContent.top, rContent.right, rContent.bottom);
}
To Render the Gadget easily I thought about using the PrintWindow Function https://msdn.microsoft.com/en-us/library/x51z0shh.aspx
What is always working?
Everything in the PrintPreview
The Border Rectangle when I'm Actually Printing
What isnt Working?
the Gadget isnt printed in some cases of the "actual Printing Process" / "Printing to Paper".
So I tried to print via PDF Creator and via 3 Local Printers in my LAN on 2 Different Windows Machines (Win7, Win8) with different Results (they seem to be always the same so i don't think its some kind of uninitialized member). Whats very weird is that I have different Results on the Machines for example there is one Printer which works for PC A but not for PC B.
I can tell you that printing just wont work within my Application so it isn't a Driver Problem. Printing normal Documents, Images fully works. And as I already told the Border is always printed.
What could be the cause of this? Do you know any Cases of such kind of Problem?
Hint:
As an workaround I tried to Copy the Gadget from the CPaintDC of the UI directly via BitBlt. In this case I have the Same Problem
To find the Issue I created a Small Test Project to recreate the Situation.
Here Is the Source Code
//Create Members
CDC pDC;
HDC hdc;
//Get Printer/Printer Settings
LPCSTR buffer = NULL;
GetDefaultPrinterName(buffer);
hdc = CreateDC("WINSPOOL", buffer, NULL, NULL);
pDC.Attach(hdc);
pDC.m_bPrinting = TRUE;
//Start Document Printing
pDC.StartDoc("TEST");
pDC.StartPage();
//Render Window
PrintWindow(&pDC,PW_CLIENTONLY);
//Render Frame Rectangle
CRect WindowRect;
GetClientRect(WindowRect);
WindowRect.MoveToXY(0,0);
CBrush brush;
brush.CreateSolidBrush(RGB(0,0,0));
pDC.FrameRect(WindowRect, &brush);
// Finish Printing
pDC.EndPage();
pDC.EndDoc();
I'm facing the same Problems here. The Same Printers are working for the same PC's.
I think the only Problem could be the Line where I create the HDC
hdcBuffer = CreateDC("WINSPOOL", buffer, NULL, NULL);
I think this call in Connection with the "printWindow" or "bitblt" is the problem.
Or could this be a MFC bug?

It looks like a MFC Bug. Somehow the Printer Driver isn't initialized Correctly. I tried several Solution's but wasn't able to got this working. It really fails in the most Simple Examples with different Results on Differnt Machines.

Related

How to get the "display stream" of a MS Windows window?

I have a program (we will call it the "virtual screen") that create a full screen window and start arbitrary programs, and with the help of hooks (CBTProc) get handles to windows that started programs create. From those handles I retrieve the content of the windows (using GetDIBits) and displays it in the "virtual screen" window.
Currently, this "virtual screen" copy content of windows and then redraw them, which make it work, sort of like a mirroring software.
Here is how I get the content of a window:
struct WindowContent {
void *pixel;
int width;
int height;
};
WindowContent getWindowContent(HWND hWnd, int height, int width)
{
WindowContent content;
WINDOWINFO windowInfo;
GetWindowInfo(hWnd, &windowInfo);
content.height = windowInfo.rcClient.right - windowInfo.rcClient.left;
content.width = windowInfo.rcClient.bottom - windowInfo.rcClient.top;
HDC hdc = GetDC(hWnd);
HDC captureHdc = CreateCompatibleDC(hdc);
HBITMAP hBitmap = CreateCompatibleBitmap(hdc, content.width, content.height);
HGDIOBJ oldHdc = SelectObject(captureHdc, hBitmap);
BitBlt(captureHdc, 0, 0, content.width, content.height, hdc, 0, 0, SRCCOPY|CAPTUREBLT);
SelectObject(captureHdc, oldHdc);
DeleteDC(captureHdc);
BITMAPINFO outputBitmapInfo = {};
outputBitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
GetDIBits(hdc, hBitmap, 0, 0, NULL, &outputBitmapInfo, DIB_RGB_COLORS);
content.pixel = (BYTE *)malloc(outputBitmapInfo.bmiHeader.biSizeImage);
outputBitmapInfo.bmiHeader.biCompression = BI_RGB;
outputBitmapInfo.bmiHeader.biBitCount = 32;
GetDIBits(hdc, hBitmap, 0, outputBitmapInfo.bmiHeader.biHeight, content.pixel, &outputBitmapInfo, DIB_RGB_COLORS);
return content;
}
My question is, how do I remove the copying part, how can I make an area on my "virtual screen" the window output for those programs ?
Emphasis on the fact that I'm trying to make created windows be the area on the "virtual screen", I don't want an additional window hidden or living on the desktop.
In my research, I've looked into Windows DWM DLLs and found some undocumented function (SignalRedirectionStartComplete or MilConnection_CreateChannel) which names look linked to what I want to do, but I don't think I should use them, as they are undocumented.
Also, the code is using Win32 API but I don't mind using another Windows API or another language (C#, DX* ...).
Forgot to mention, I have already thought about using the DWM thumbnail stuff, but it's not that reliable enough for what I'm trying to do.
As far as I understand Windows 10 uses DX under the hood for all display output, for GDI, and even for Vulkan / OpenGL programs, and someone used it to make a lib that
gets DX 10 texture from a window (). Is it possible to make something similar, that, for a specific HWND, set its "output" to a texture or some region in
memory (swapchain redirection ?) instead of the screen and then display the output in another program (in my case, on the "virtual screen" window) ?
The DWM was a reasonable place to look. It has some documented functions to get you at least a little closer to what you want.
You can register your window as a "thumbnail" viewer using DwmRegisterThumbnail. Then you (probably) call DwmUpdateThumbnailProperties to tell it how to draw to your window (e.g., set opacity, rectangle to draw to, and whether to draw the whole source window, or just its client area). When you're done, you call DwmUnregisterThumbnail to unhook from displaying it.
This is only a little closer to what you want though--it eliminates your having to copy bitmaps from the source into your own window--but that's about all it does. The target application will still have its own window running elsewhere.
If you want to do more to hide the application, you could create another desktop, and display the application in that desktop. If you don't provide a way to switch desktops, that can keep it pretty well hidden. On the other hand, there are external tools that will let the user change desktops, which would let them see the application directly.
One other avenue to consider (for a subset of applications) would be COM. Part of what COM supports is having a COM server that displays its output inside the frame of some COM client's window. That's no longer nearly the big thing it once was, but (I believe) all the code to support it is still available. But, it only works for applications that are specifically written to support it (which, honestly, isn't a huge number). The code for this isn't exactly trivial either.

Drawing to the desktop via injection

I'd like to draw to the desktop wallpaper area with directX 9 in particular. Under the icons and text above the wallpaper.
Similar to Okozo or one of VLC's modes, or Dreamscene.
So there's a lot of similar questions to this but no working examples or tutorials.This A simmilar question but different approach seems pretty useful. A few years ago I was searching and found this site and code.
It's perfect aside from one big issue the icon text gets blocky even with alpha blending. I tried a few fixes but I wasn't able to find any helpful documentation maybe I just wasn't using the right words for searching, maybe it's proprietary. I think I fixed that with a call to invalidate the desktop area but I can't really tell as in the process I messed up the alpha values for the text so it doesn't properly draw the font color. So how do I alter the text for proper alpha blending?
Pouet's links are all dead
I know I should post a snippet but I can't pin down where the problem is as it's more an unexpected feature.
I've been searching for this code for too long.
I'd like to write a Dreamscene like app witch can render dynamic contents other than just video files, and this one may be the most hopful solution.
I compiled your code in VS2010 Win7x64 and found:
Desktop icon text become transparent just like Dreamscene do when the window is like:
0x00150138 "Program Manager" Progman
0x000605D6 "" SHELLDLL_DefView
0x000C05BA "FolderView" SysListView32
Desktop icon text become normal but not clear enough when the window is like:
0x000B007C "" WorkerW
0x000605D6 "" SHELLDLL_DefView
0x000C05BA "FolderView" SysListView32
0x000C05BA "FolderView" SysListView32
0x000511E2 "" WorkerW
0x00150138 "Program Manager" Progman
I tried this method Draw Behind Desktop Icons in Windows 8 to make the window status always be like the second condition; and tried to draw on WorkerW window above Progman window with D3D, but got nothing rendered out.
So far there's nothing helpful, dumping the bitmap used by memoryDC may help, which I'll try latter.
If you got any further approach, please let me know.
It has been long time since I last use English, Sorry for my mistake if any.
Update:Clear Icon Text got!
add this under d3ddev->BeginScene();
d3ddev->SetSamplerState(0,D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
d3ddev->SetSamplerState(0,D3DSAMP_MAGFILTER, D3DTEXF_GAUSSIANQUAD);
and this:
HWND desktop = GetDesktopWindow();
HWND explorer = FindWindowEx(desktop, 0, _T("Progman"), _T("Program Manager"));
SendMessageTimeout(explorer, 0x052C, 0, 0, SMTO_NORMAL, 3000, NULL);
HWND defView = 0;
HWND worker = 0;
while(!defView) {
worker = FindWindowEx(desktop, worker, _T("WorkerW"), 0);
if(worker) {
defView = FindWindowEx(worker, 0, _T("SHELLDLL_DefView"), 0);
}
else break;
}
if (!worker){ /*DBG("First WorkerW failed");*/ return 0;}
worker = FindWindowEx(desktop, (HWND)worker, _T("WorkerW"), 0); //find the next WorkerW
if (!worker){ /*DBG("Created WorkerW not found");*/ return 0;}
Still drawing on the listView, but worker window must exist. This code runs with Aero Theme enabled only.

Using d3d9's backbuffer functionalities correctly

I'm trying to write a simple DLL which allow me to take a screenshot of the program calling it.
The program give me its Window Handle using the DLL call.
The CreateDevice functions, CreateOffScreenPlainSurface, works fine using the provided handle, according to HRESULT values returned.
But the output image is blank, then I think that I'm not using the DirectX's GetBackBuffer functions correctly.
Here is how I proceed:
HRESULT GFBD_r = g_pd3dDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pSurface);
HRESULT LR_r = pSurface->LockRect(&lr, &rect, D3DLOCK_READONLY);
memcpy(&Frame[0], lr.pBits, Width*Height*4);
pSurface->UnlockRect();
My Frame vector is still remaining empty. Maybe the problem came from Multisampling ? I don't exactly understand how does it works, except that i'm using d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; in my D3DPRESENT_PARAMETERS .
Creating a D3D device for an existing window does not allow you to capture its contents, even if that window is rendered to using hardware acceleration. If there is already a D3D device for the window, the API call to create the device should fail (iirc). If the window is drawn to using regular Windows APIs (i.e. GDI), the D3D content will, depending on the Windows version, be either composed with that other content or behave in an undefined way. Such composition would happen after you access the back buffer, and (likely) elsewhere.

C++ Win32, easiest way to show a window with a bitmap

It's only for 'debugging' purposes, so I don't want to spend a lot of time with this, nor it is very important. The program exports the data as a png, jpg, svg, etc... -so it's not a big deal, though it could be good to see the image while it is being generated. Also, the program is going to be used in a Linux server; but I'll limit this 'feature' to the Win version.
I also don't want to use a library, except if it is very, very lightweight (I used CImg for a while, but I wasn't very happy with its speed, so I ended up writing the important functions myself and just using libjpeg and libpng directly).
I have the image in an ARGB format (32bpp), though converting the format won't be a problem at all. I would like to use Win32, creating a window from a function deep inside the code (no known hInstance, etc), and writing the bitmap. Fast and easy, hopefully.
But I don't know the win32api enough. I've seen that the only option to draw (GDI) is trough a HBITMAP object... Any code snippet or example I can rely on? Any consideration I might not overlook? Or maybe -considering my time constrains- should I just forget it?
Thanks!
The biggest piece of work here is actually registering the window class and writing a minimal window procedure. But if this is debug only code, you can actually skip that part. (I'll come back to that later).
If you have an HBITMAP, then you would use BitBlt or StretchBlt to draw it, but if you don't already have the image as an HBITMAP, then StretchDIBits is probably a better choice since you can use it if you only have a pointer to the bitmap data. You have to pass it a source and destination rectangle, a BITMAPINFOHEADER and a pointer to the raw bitmap data. Something like this
SIZE sBmp = { 100, 200 };
LPBITMAPINFOHEADER pbi; // the bitmap header from the file, etc.
LPVOID pvBits; // the raw bitmap bits
StretchDIBits (hdc, 0, 0, sBmp.cx, sBmp.cy,
0, 0, sBmp.cx, sBmp.cy,
pvBits, pbi,
DIB_RGB_COLORS,
SRCCOPY);
So the next part is how do I get a HDC to draw in? Well for Debug code, I often draw directly to the screen. HDC hdc = GetDC(NULL) will get a DC that can draw to the screen, but there are security issues and it doesnt' work the same with Aero in Windows Vista, so the other way is to draw onto a window. If you have a window that you can just draw over, then HDC hdc = GetDC(hwnd) will work.
The advantage of doing it this way is that you don't have to create and show a window, so it's less disruptive of code flow, It's helpful for debugging a specific problem, but not the sort of thing you can leave turned on all of the time.
For a longer term solution, You could create a dialog box and put your bitmap drawing call in the WM_PAINT or WM_ERASEBKGND message handler for the dialog box. But I don't recommend that you show a dialog box from deep inside code that isn't supposed to be doing UI. Showing a window, especially a dialog window will interfere with normal message flow in your application. If you want to use a dialog box for this bitmap viewer, then you want that dialog window to be something that the User shows, and that you just draw onto if it's there.
If you don't have access to an HINSTANCE, it's still possible to show a dialog box, it's just more work. That's sort of a different question.
About all you need is a handle to a device context (HDC). To display your data on it:
CreateDibSection to create a DIBSection.
Copy your data to the memory block returned by CreateDibSection.
create a DC compatible with the target DC.
Select the DIBSection into your newly created DC.
BitBlt (or StretchBlt) from your DC to the target DC.

When using SDL_SetVideoMode, is there a way to get the internal SDL_Window pointer or ID?

If you create a window by using SDL_SetVideoMode(), you are returned a surface, not a window handle. Is there a way to get the SDL_Window handle? I know there is a SDL_GetWindowFromID function, but I'm also not sure how to get the ID, other than the SDL_GetWindowID function, which would require me to already have the window handle.
Any suggestions? Note that it is very important that I maintain cross platform portability, so I prefer to stick with built in SDL functionality if at all possible.
If it helps any, I'm trying to get and set the window position and window size, and those functions require a window handle.
Thanks!
EDIT: I should mention also that I am changing video modes at the user's request, so I cannot just use the default ID of 1, since this ID changes every time I call SDL_SetVideoMode().
I had the same problem with SDL-1.2.15 for windows ,but the problem solved by GetActiveWindow.
You can get SDL window handle like this :
...
screen = SDL_SetVideoMode(w, h, 0, flags);
...
HWND hnd= GetActiveWindow();
See this :
GetActiveWindow function
I had this exact problem - old SDL 1.2 only uses one window, so it keeps the handle to itself. Here's the method I found from reading the source code:
Include SDL_syswm.h then get the window handle using SDL_GetWMInfo
e.g. my code for getting the handle in Windows:
SDL_SysWMinfo wmInfo;
SDL_GetWMInfo(&wmInfo);
HWND window = wmInfo.window;
SDL_SetVideoMode returns a surface based on the video frame buffer, not on a window (just like SDL_GetVideoSurface). You seem to assume that all surfaces correspond to windows, but that is not the case.