Windows Bitmap print driver winddk OEMNextBand, OEMSendPage - windows

I am observing the OEMSendPage doesn't get invoked always.
When does OEMSendPage get called?
We have a legacy printer which does some processing inside OEMSendPage. I hate to move it to a different place in the process. It has been working but now I am working on some enhancements and need to figure this out.
The other commands are OEMStartPage, OEMStartDoc, OEMTextOut, OEMStartBanding,OEMNextBand,OEMEndDoc.
These all are called except SendPage.
Currently I am attaching VS to spool.exe and the printer is installed at File:port.
When does SendPage command get called?
static const DRVFN s_aOemHookFuncs[] =
#if defined(IMPL_TEXTOUT)
{INDEX_DrvTextOut, (PFN)OEMTextOut},
#endif
#if defined(IMPL_TRANSPARENTBLT)
{INDEX_DrvTransparentBlt, (PFN)OEMTransparentBlt},
#endif
#if defined(IMPL_STARTDOC)
{INDEX_DrvStartDoc, (PFN)OEMStartDoc},
#endif
#if defined(IMPL_ENDDOC)
{INDEX_DrvEndDoc, (PFN)OEMEndDoc},
#endif
#if defined(IMPL_STARTPAGE)
{INDEX_DrvStartPage, (PFN)OEMStartPage},
#endif
#if defined(IMPL_SENDPAGE)
{INDEX_DrvSendPage, (PFN)OEMSendPage},
#endif
As an update I found on the following link
https://learn.microsoft.com/en-us/windows-hardware/drivers/print/rendering-a-print-job#-banding-not-in-use
So I added the part of processing to NextBand also including SendPage.
But something is not correct. OEMNextBand gets called multiple times and the PCL has many pages. The original is only one page but PCL has so many pages.
Can anyone suggest?
char gszPageText[32767];
BOOL APIENTRY
OEMStartBanding(
SURFOBJ *pso,
POINTL *pptl
)
{
return (pOemPDEV->m_pfnDrvStartBanding)(pso,
pptl);
}
BOOL APIENTRY
OEMNextBand(
SURFOBJ *pso,
POINTL *pptl
)
/*++
{
//VERBOSE(L"OEMNextBand entry.");
PDEVOBJ pDevObj = (PDEVOBJ)pso->dhpdev;
POEMPDEV pOemPDEV = (POEMPDEV)pDevObj->pdevOEM;
// Punt call back to UNIDRV.
BOOL b= (pOemPDEV->m_pfnDrvNextBand)(pso,
pptl);
if (pptl != NULL && pptl->x == -1 && pptl->y == -1)
{
BOOL c = DOPCLProcessingPerPage(pso, gFirstPage, gszPageText);
if (!c)
return TRUE;
}
//if (!CreatePCLRasterGraphicPage(pso, gFirstPage, gszPageText))
//return TRUE;
return b;
}
DrvEnableSurface to call EngModifySurface to disable banding. I don't know the pros and cons of disabling banding w.r.t performance. This is a bitmap driver
Edited
**For Mono**
StartDoc
-- then for as many pages in the document
StartPage
SendPage
EndDoc
**For Colour**
StartDoc
-- then for as many pages in the document
StartPage
StartBanding
-- then for so many bands
NextBand
SendPage ?? (what is the send page equivalent here for color)
EndDoc
**
Edited for EnableDriverSurface
static const DRVFN s_aOemHookFuncs[] =
{
{INDEX_DrvEndDoc, (PFN)OEMEndDoc},
{INDEX_DrvSendPage, (PFN)OEMSendPage},
{INDEX_DrvStartBanding, (PFN)OEMStartBanding},
{INDEX_DrvNextBand, (PFN)OEMNextBand},
{INDEX_DrvTextOut, (PFN)OEMTextOut},
{INDEX_DrvStartPage, (PFN)OEMStartPage},
{INDEX_DrvStartDoc,(PFN)OEMStartDoc},
//added this
{INDEX_DrvEnableSurface ,(PFN)DrvEnableSurface}
// {INDEX_DrvEnableSurface, (PFN)DrvEnableSurface},
};
HSURF APIENTRY DrvEnableSurface(
DHPDEV dhpdev)
{
HSURF hsurf;
SIZEL sizl;
ULONG ulBitmapType;
FLONG flHooks;
// Create engine bitmap around frame buffer.
PDEVOBJ ppdev = (PDEVOBJ)dhpdev;
POEMPDEV pOemPDEV = (POEMPDEV)ppdev->pdevOEM;
EngModifySurface(hsurf,......)
return(hsurf);
}
**

Related

A crash on V8' Context::New

I implement a wrapper around the Google V8 engine. I wrote a class:
class Es
{
public:
Es();
~Es();
int Init(const char* exec_path);
int CreateContext(uint& id);
int RemoveContext(const uint id);
protected:
Global<Context> global_context;
std::map<uint, Persistent<Context>*> contexts;
Isolate* isolate = nullptr;
private:
uint next_id = 1;
};
I want to create Contexts, hold them in the contexts var, and remove them oneday. So, I init the V8 engine:
int Es::Init(const char* exec_path)
{
v8::V8::InitializeICUDefaultLocation(exec_path);
v8::V8::InitializeExternalStartupData(exec_path);
std::unique_ptr<Platform> platform = platform::NewDefaultPlatform();
V8::InitializePlatform(platform.get());
V8::Initialize();
Isolate::CreateParams create_params;
create_params.array_buffer_allocator = ArrayBuffer::Allocator::NewDefaultAllocator();
isolate = Isolate::New(create_params);
if (!isolate)
return InitError;
return Success;
}
And after that I want to create a context, using int Es::CreateContext(uint& id). Its called after Init.
int EasyProspect::CreateContext(uint& id)
{
if (!isolate)
return NotInitializedError;
Isolate::Scope isolate_scope(isolate);
HandleScope handle_scope(isolate);
Local<Context> local_context = Context::New(isolate);
Persistent<Context> context(isolate, local_context);
contexts.emplace(id, &context);
return Success;
}
But I can't do that, the code crashes on Context::New(isolate). Why? isolate is not null, I enter the local scope...
Your best bet is to compile in Debug mode and run in a debugger. Then it should be easy to tell what's causing the crash.
(At the very least, you should post a complete reproducible example, including specifying the V8 version you're working with, how that's built/configured, and how you're compiling your code.)
If I had to guess: the Platform and the ArrayBuffer::Allocator need to stay alive for as long as you want to use the V8 instance, but in your code they are both destroyed at the end of Es::Init. Since Es is a wrapper class, you can easily add fields there to keep them around.

Which Windows API in C++ will help me in identifying which Dialog Class the Current ComboBox is using?

How can I know that for a particular ComboBox which Dialog Style is being used? Is there any Win32 API which can give me that information?
I am using CDialog for a few ComboBox, CDialogEx for some, and an in-house Dialog class, let's say Ctl3dDialogEx, for others. GetClassName() will return the Class name of the ComboBox (if I am passing a ComboBox Handler) which can be "CComboBox".
Is there any Win32 API where I will pass the ComboBox Handler and it will return back to me the Dialog class name, for eg : "CDialog", "CDialogEx", "Ctl3dDialogEx", etc?
Below code will help to understand maybe:
void ComboBox_DoSomeManipulation( HWND hldg , int n )
{
/*"hldg" is the handler of the Current ComBobox */
LPTSTR lpClassName;
int nMaxCount = 256;
/*This will return "CComboBox" as value in lpClassName */
GetClassName(hldg , lpClassName , _count_of(nMaxCount));
/*Is there any WIN API like above which can give */
/* Dialog class information like CDialog, CDialogEx */
/* which the ComboBox is using ? */
}
If your combo-box can somehow get hold of a genuine pointer to its parent window, then you can use dynamic_cast<CDialogEx*>(pParent) to see if it's CDialogEx (returns nullptr if not). You will need several separate checks, starting from the most derived class! So, if your Ctl3dDialogEx is derived from CDialogEx, then:
. . .
CWnd *pParent = pCombo->GetParent(); // This, as is, is not valid code!
if (dynamic_cast<Ctl3dDialogEx*>(pParent) != nullptr) {
// It's a Ctl3dDialogEx parent
}
else if (dynamic_cast<CDialogEx*>(pParent) != nullptr) {
// It's a CDialogEx
}
else { // Assuming no other options …
// It's a CDialog
}
I would recommend making an accessible (static?) copy of the parent window's this pointer during initialisation, if you can. But there are other ways …
For example, assuming you have control over the definition of ComboBox_DoSomeManipulation and when it's called, change the first argument from an HWND to a CWnd* and, when you call it, use this rather than this->m_hwnd. (But this depends on the structure of your code!)
There is no Windows API help since all those dialogs will be subclassing the Windows DIALOG class. If this is all in process, and you are using the same MFC instance, you might be able to do this:
CWnd* pWnd = CWnd::FromHandlePermanent(hdlg);
if (pWnd != NULL)
{
if (pWnd->GetRuntimeClass() == RUNTIME_CLASS(CDialog))
{
}
else if (pWnd->GetRuntimeClass() == RUNTIME_CLASS(CDialogEx))
{
}
else if (pWnd->GetRuntimeClass() == RUNTIME_CLASS(CDialogxyz))
{
}
}
Back in the old days, MS compilers used with MFC didn't play well with dynamic_cast<>, so generally, when using MFC, I don't use it. I probably should have more trust in it, but I was stuck using Visual C++ 6 until 2008, so I am probably a little jaded. The more "standard" "MFC way" is to use the MFC macros...
Another possible ways is something like:
if (CDialogxyz* pDlgxyz = DYNAMIC_DOWNCAST(CDialogxyz, pWnd))
{
}
else if (CDialogEx* pDlgEx = DYNAMIC_DOWNCAST(CDialogEx, pWnd))
{
}
else if (CDialog* pDlg = DYNAMIC_DOWNCAST(CDialog, pWnd))
{
}

Zero-Copy messaging with zmqpp

ZeroCopy messaging is something that can be implemented in zeromq, but is it possible to use it with the zmqpp c++ bindings? There is almost no documentation, and I was not able to find anything in the examples...
I would switch to cppzmq.
It's a more active project and maintained by some of the core libzmq people.
It's header only and has support for zero copy.
Just simply use zmqpp::message::copy().
In the zmqpp source code we can see:
void message::copy(message const& source)
{
_parts.resize( source._parts.size() );
for(size_t i = 0; i < source._parts.size(); ++i)
{
_parts[i] = source._parts[i].copy();
}
// we don't need a copy of the releasers as we did data copies of the internal data,
//_releasers = source._releasers;
//_strings = source._strings
}
the _parts which defined as:
private:
typedef std::vector<frame> parts_type;
parts_type _parts;
so, source._parts[i].copy() actually call zmqpp::frame::copy() which defined here:
frame frame::copy() const
{
frame other( size() );
other._sent = _sent;
if( 0 != zmq_msg_copy( &other._msg, const_cast<zmq_msg_t*>(&_msg) ) )
{
throw zmq_internal_exception();
}
return other;
}
zmqpp::frame::_msg in the code snippet is defined as zmq_msg_t. All zmq_msg_t object in the frame objects of source zmqpp::message object been zero copied by zmq_msg_copy to new zmqpp::message object.
so, zmqpp::message::copy() help us get a new zmqpp::message object which it's all frame is zero copied from the source zmqpp::message object.

WxWidgets and modern opengl (3.3+)

Does anyone know if the WxWidgets library plays well with modern shader style openGL (3.3+)? All the stuff I found seems to be using the old style. I'm looking to use either QT or WxWidgets for my application, but it seems like getting shader stuff to work with widgets might be a nightmare. Does anyone have experience with this?
In wxWidgets >= 3.1 using wxGLContext with an appropriate Core-context wxGLContextAttrs ought to work:
wxGLContextAttrs cxtAttrs;
cxtAttrs.CoreProfile().OGLVersion(3, 3).EndList();
As Ripi2 pointed out from the pyramid sample:
//We create a wxGLContext in this constructor.
//We do OGL initialization at OnSize().
MyGLCanvas::MyGLCanvas(MyFrame* parent, const wxGLAttributes& canvasAttrs)
: wxGLCanvas(parent, canvasAttrs)
{
m_parent = parent;
m_oglManager = NULL;
m_winHeight = 0; // We have not been sized yet
// Explicitly create a new rendering context instance for this canvas.
wxGLContextAttrs ctxAttrs;
#ifndef __WXMAC__
// An impossible context, just to test IsOk()
ctxAttrs.PlatformDefaults().OGLVersion(99, 2).EndList();
m_oglContext = new wxGLContext(this, NULL, &ctxAttrs);
if ( !m_oglContext->IsOK() )
{
#if wxUSE_LOGWINDOW
wxLogMessage("Trying to set OpenGL 99.2 failed, as expected.");
#endif // wxUSE_LOGWINDOW
delete m_oglContext;
ctxAttrs.Reset();
#endif //__WXMAC__
ctxAttrs.PlatformDefaults().CoreProfile().OGLVersion(3, 2).EndList();
m_oglContext = new wxGLContext(this, NULL, &ctxAttrs);
#ifndef __WXMAC__
}
#endif //__WXMAC__
if ( !m_oglContext->IsOK() )
{
wxMessageBox("This sample needs an OpenGL 3.2 capable driver.\nThe app will end now.",
"OpenGL version error", wxOK | wxICON_INFORMATION, this);
delete m_oglContext;
m_oglContext = NULL;
}
else
{
#if wxUSE_LOGWINDOW
wxLogMessage("OpenGL Core Profile 3.2 successfully set.");
#endif // wxUSE_LOGWINDOW
}
}

Shell BrowseForFolder preselected path

I have this call:
oShell.BrowseForFolder(Me.hwnd, "Select path:", 0, "C:\dir\")
This opens a standard file browser dialog with "C:\dir\" as root.
My problem is that you can not browse above the root folder. (as specified in doc http://msdn.microsoft.com/en-us/library/bb774065(v=vs.85).aspx)
Any suggestions on oppening this dialog with a selected path and full browsing posibility?
Thanks
The way to do this involves calling the underlying API, SHBrowseForFolder().
Since you want the entire shell namespace to be available you need to pass NULL as pidlRoot. In order to select your desired folder you will need to provide a callback in lpfn. Make this callback respond to BFFM_INITIALIZED by setting the selected folder. This selection is performed by sending the BFFM_SETSELECTION message to the dialog's window handle (passed to the callback function).
No code because I don't have VB6, but hopefully this outline of the method is enough to get you on your way.
Karl E Peterson's excellent website contains a sample which demonstrates the API call SHBrowseForFolder with a callback, as in David Heffernan's answer.
The KeyStuff project
Look at MFolderBrowse.bas, routine BrowseForFolderByPIDL which passes a callback function BrowseCallbackProc.
Try the old CCRP project. It has a nicely done implementation of the Browse dialog. I used it in several of my projects and it has properties to address the issue you are having.
Here a code ready for copy and paste in a C++ class:
// static
int CALLBACK Func::FolderBrowserCallback(HWND h_Dlg, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
if (uMsg == BFFM_INITIALIZED)
{
// Requires Windows XP or higher
SendMessageW(h_Dlg, BFFM_SETEXPANDED, TRUE, lpData);
}
return 0;
}
// returns an empty string u16_PathOut if an error occurrs or if the user cancels the dialog
void Func::GetOpenFolder(HWND h_Owner,
const WCHAR* u16_Title, // IN: Title at the top of dialog
int s32_CsidlRoot, // IN: Root folder for treeview (CSIDL_DRIVES -> My Computer)
const WCHAR* u16_Preselect, // IN: NULL or the folder to be preselected and expanded
WCHAR* u16_PathOut) // OUT: selected path
{
u16_PathOut[0] = 0;
// CoInitialize(NULL);
// InitCommonControls();
ITEMIDLIST* pk_RootPIDL = NULL; // NULL -> Root = Desktop
SHGetSpecialFolderLocation(h_Owner, s32_CsidlRoot, &pk_RootPIDL);
BROWSEINFOW k_Info = {0};
k_Info.hwndOwner = h_Owner;
k_Info.pidlRoot = pk_RootPIDL;
k_Info.lpszTitle = u16_Title;
k_Info.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI;
if (u16_Preselect)
{
k_Info.lpfn = FolderBrowserCallback;
k_Info.lParam = (LPARAM)u16_Preselect;
}
// DO NOT DISABLE Wow64FsRedirection HERE !!
LPITEMIDLIST pk_IDlist = SHBrowseForFolderW(&k_Info);
if (pk_IDlist)
{
SHGetPathFromIDListW(pk_IDlist, u16_PathOut);
CoTaskMemFree(pk_IDlist);
}
CoTaskMemFree(pk_RootPIDL);
}

Resources