If personal information is included in the requested print using C++ language, cancel the current print and print again after receiving approval from the server.
※This event is raised when the user directly outputs an open file.
(In other words, if the user directly requests printing of an open file in the same way as ctrl+p, printing will be requested for the open file because the dll I created works.)
Approval is at EndDoc, the point at which the print is almost finished.
The problematic part is how to print again.
I was using the implementation to request a print again as shown below.
[refer to variable]
RequestDevModeW -> When printing is requested for the first time, the information is saved and used for reprint. (Saved when calling DocumentPropertiesW API.)
RequestDOCInfoW -> When printing is requested for the first time, the information is saved and used for reprint. (This is a structure stored in StartDocW when requesting a print for the first time.)
nPageCnt -> The number of startpage <-> Endpage is stored when the first print request is made.
[Code]
//... skip ...//
hReprintDC = CreateDCW(NULL, wszPrintName, NULL, &RequestDevModeW);
if (hReprintDC)
{
RequestDOCInfoW.lpszDocName = (LPCWSTR)wszDocName;
StartDocW(hReprintDC, &RequestDOCInfoW);
for (int nPage = 0; nPage < nPageCnt; ++nPage)
{
StartPage(hReprintDC);
EndPage(hReprintDC);
}
EndDoc(hReprintDC);
DeleteDC(hReprintDC);
g_hRePrintDC = NULL;
}
//... skip ...//
However, the code above is causing an error when displaying textbox in some documents (excel, word).
So I used the ShellExecuteEX API.
It prints very well, but I can't get the print attributes to work.
What I mean by print properties is that you have no control over these details, such as printing specific pages.
I'm curious about how to make a detailed request for a print using C++ code.
In addition, the print dialog should be output as it is with the existing specifications without being displayed.
Related
I have the DirectX Debug Layer working and it outputs errors and warnings to the output window in visual studio. Like this for example (not the actual issue I'm facing):
D3D11 WARNING: ID3D11DeviceContext::OMSetRenderTargets: Resource being set to OM RenderTarget slot 0 is still bound on input! [ STATE_SETTING WARNING #9: DEVICE_OMSETRENDERTARGETS_HAZARD]
I have a custom logging system that saves to files and prints in other windows. I'd like to capture the debug message strings, and display them in my own way. Is this supported? If so how do I do it?
Since I had this problem myself and found the previous answer a bit lackluster, I want to give a more detailed solution, now that I've got this working:
All API calls I will reference can be found here
One can get messages out of DirectX11 by reading them from an internal message queue, that can be accessed by calling ID3D11InfoQueue::GetMessage, which takes the index of the message to get and fills a provided buffer with a D3D11_MESSAGE struct, that contains all the wanted information (Severity, Category, ID and Text).
However, I discovered that this buffer was empty (by calling ID3D11InfoQueue::GetNumStoredMessages) when I tried to iterate over it. That seemed to be due to some filtering going on. In order for the runtime to actually fill this buffer, I first had to call ID3D11InfoQueue::PushEmptyStorageFilter, which pushes a filter that doesn't filter out any messages:
//HANDLE_HRESULT is just a macro of mine to check for S_OK return value
HANDLE_HRESULT(debug_info_queue->PushEmptyStorageFilter());
This filtering is the part that is actually discussed in the blog post that is linked in Chuck Walbourn's answer (allthough the link only directs me to the main page, the actual blog post is here). It doesn't contain any info on how to redirect the messages though.
Once the messages are generated, you can iterate over them like so:
UINT64 message_count = debug_info_queue->GetNumStoredMessages();
for(UINT64 i = 0; i < message_count; i++){
SIZE_T message_size = 0;
debug_info_queue->GetMessage(i, nullptr, &message_size); //get the size of the message
D3D11_MESSAGE* message = (D3D11_MESSAGE*) malloc(message_size); //allocate enough space
HANDLE_HRESULT(debug_info_queue->GetMessage(i, message, &message_size)); //get the actual message
//do whatever you want to do with it
printf("Directx11: %.*s", message->DescriptionByteLength, message->pDescription);
free(message);
}
debug_info_queue->ClearStoredMessages();
debug_info_queue is the ID3D11InfoQueue interface and can be obtained like so:
ID3D11InfoQueue* debug_info_queue;
device->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&debug_info_queue);
You use the ID3D11InfoQueue interface to implement your own debug message output.
using Microsoft::WRL::ComPtr;
ComPtr<ID3D11Debug> d3dDebug;
if (SUCCEEDED(device.As(&d3dDebug)))
{
ComPtr<ID3D11InfoQueue> d3dInfoQueue;
if (SUCCEEDED(d3dDebug.As(&d3dInfoQueue)))
{
See this blog post
In my application a user can have multiple documents open and print all documents to PDF's using a "Microsoft print to pdf" option when they are prompted at the print dialog window, after which they choose the destination folder. Now what happens is that if there are 30 documents selected for print, an inconsistent amount are successfully printed to pdf in the desired folder each time it is run. Sometimes all are successful and other times not. I found that files with unicode character names like this "敥敥敥敥敥敥敥敥" where being created in the same directory as the file of code that contains this print to pdf process. I can rename these files with a ".pdf" extension and they are working pdf documents.
Here is the part of code concerned:
DOCINFO docInfo;
memset(&docInfo, 0, sizeof(docInfo));
docInfo.cbSize = sizeof(docInfo);
docInfo.lpszDocName = csPlanoName;
docInfo.lpszOutput = csOutputDir + csPlanoName + csExtension;
if(dc.StartDoc(&docInfo) > 0) {
//printing process continues
}
I found that by stepping through the code, the StartDoc function call would change docInfo.lpszOutput to the same unicode characters "敥敥敥敥敥敥敥敥". This would not happen all the time, and does not happen with specific files when testing. One test a document will print to pdf successfully, another test with the same document and it will create the file with the name "敥敥敥敥敥敥敥敥".
Any help with this would be greatly appreciated.
Regards,
Chris
What are csPlanoName csOutputDir? docInfo.lpszDocName and docInfo.lpszOutput must be pointers to null-terminated strings and since you are using csOutputDir + csPlanoName + csExtension that won't work with regular pointers something else might be happening here. Make sure that result of csOutputDir + csPlanoName + csExtension is not getting implicitly cast to pointer and then going out of scope.
using a string conversion macro seems to have solved my problem, successfully tested outcome 10+ times.
CString csFullpath = csOutputDir + csPlanoName + csExtension;
docInfo.lpszOutput = CT2W(csFullpath);
I just want to know that how to retrieve all the record from universe database table using universe basic subroutine.I am new in universe.
Perhaps something like this in the unibasic
OPEN "filename" to FIL ELSE STOP 201,"cannot open filename"
EXECUTE "SELECT filename"
LOOP WHILE READNEXT ID
READ REC FROM FIL,ID ELSE REC = ""
* you now have the entire row in REC
REPEAT
Can you provide more information on what you are trying to do?
Having a subroutine call return the entire contents of a UniVerse file could return a large amount of data. I would expect you would be better off only returning a subset of the items so the calling routine can process a bit at a time.
New content based on comment:
Ok, since you mentioned a type 19 file, I assume you want to read one file from the directory/folder the file points to.
In your subroutine, you can use OPEN on the type 19 file, and use the READ command to read the file. ( Note that you can also use READU, READL, MATREAD, MATREADU, or MATREADL to get the entire file in the directory/folder, depending on if/how you want to lock the item and if you want the data in a dynamic or dimensioned array. If you only need a specific attribute you can then use READV, READVL or READVU commands.
Or, since this is a type 19 file, you can use sequential reads. Open the file with OPENSEQ and read with the READSEQ or READBLK command.
There is an article and sample code on GitHub on how to execute U2 UniVerse Subroutine.
Execute Rocket MV U2 Subroutine Asynchronously using C# (async\await) and U2 Toolkit for .NET. Convert Subroutine Multi-Value Output to Json/Objects/DataTable
These sample code are based on C# (async\await), but you can use for synchronous programming as well with little code tweak.
For article:
Go to this link :
https://github.com/RocketSoftware/multivalue-lab/tree/master/U2/Demos/U2-Toolkit/AsyncAwait/Execute_Subroutine_Async
Read ‘Subroutine-Async.docx’ file.
Sample Code for this article on GitHub
Go to this link :
https://github.com/RocketSoftware/multivalue-lab/tree/master/U2/Demos/U2-Toolkit/AsyncAwait/Execute_Subroutine_Async
OPEN '',FILENAME TO F.FILE ELSE STOP
SELECT F.FILE
LOOP
READNEXT K.FILE ELSE EXIT
READ R.FILE FROM F.FILE, K.FILE ELSE NULL
PRINT R.FILE
REPEAT
PRINT "All over Red Rover"
Filename should be in quotes, i.e "MYFILE" or 'MYFILE'
The loop will repeat till all records have been read and will then exit.
I am currently stuck in this problem that I do not have any idea to fix. It is regarding a previous question that I have asked here before. But I will reiterate again as I found out the problem but have no idea to fix it.
My program accesses a text file that is updated constantly every millisecond 24/7. It grabs the data line by line and does comparison on each of the line. If any thing is "amiss"(defined by me), then I log that data into a .csv file. This program can be run at timed intervals(user defined).
My problem is that this program works perfectly fine on my computer but yet it doesnt on my clients computer. I have debug the program and these are my findings. Below is my code that I have reduced as much possible to ease the explanation process
int result;
char ReadLogLine[100000] = "";
FILE *readLOG_fp;
CString LogPathName;
LogPathName = Source_Folder + "\\serco.log"; //Source_Folder is found in a .ini file. Value is C:\\phython25\\xyratex\\serco_logs
readLOG_fp = fopen(LogPathName, "r+t");
while ((result = fscanf(readLOG_fp, "%[^\n]\n", ReadLogLine)) != EOF) // Loops through the file till it reaches the end of file
{
Sort_Array(); // Here is a function to sort the different lines that I grabbed from the text file
Comp_State(); // I compare the lines here and store them into an array to be printed out
}
fclose(readLOG_fp);
GenerateCSV(); // This is my function to generate the csv and print everything out
In Sort_Array(), I sort the lines that I grab from the text file as they could be of different nature. For example,
CStringArray LineType_A, LineType_B, LineTypeC, LineTypeD;
if (ReadLogLine == "Example line a")
{
LineType_A.add(ReadLogLine);
}
else if (ReadLogLine == "Example line b")
{
LineType_B.add(ReadLogLine);
}
and so on.
In CompState(), I compare the different values within each LineType array to see if there are any difference. If it is different, then I store them into a seperate array to print. A simple example would be.
CStringArray PrintCSV_Array;
for (int i = 0; i <= LineType_A.GetUpperBound(); i++)
{
if (LineType_A.GetAt(0) == LineType_A.GetAt(1))
{
LineType_A.RemoveAt(0);
}
else
{
LineType_A.RemoveAt(0);
PrintCSV_Array.Add(LineType_A.GetAt(0);
}
}
This way I dont have an infinite amount of data in the array.
Now to the GenerateCSV function, it is just a normal function where I create a .csv file and print whatever I have in the PrintCSV_Array.
Now to the problem. In my client's computer, it seems to not print anything out to the CSV. I debugged the program and found out that it keeps failing here.
while ((result = fscanf(readLOG_fp, "%[^\n]\n", ReadLogLine)) != EOF) // Loops through the file till it reaches the end of file
{
Sort_Array(); // Here is a function to sort the different lines that I grabbed from the text file
Comp_State(); // I compare the lines here and store them into an array to be printed out
}
fclose(readLOG_fp);
It goes into the while loop fine as I did some error checking there in the actual program. The moment it goes into the while loop it breaks out of it suggesting to me it reach EOF for some reason. When that happens, the program has no chance to go into both the Sort_Array and Comp_State functions thus giving me a blank PrintCSV_Array and nothing to print out.
Things that I have checked is that
I definitely have access to the text file.
My thoughts were because the text file is updated every
millisecond, it may have been opened by the other program to write
into it and thus not giving me access OR the text file is always in
an fopen state therefore not saving any data in for me to read. I
tested this out and the program has value added in as I see the KB's
adding up in front of my eyes.
I tried to copy the text file and paste it somewhere else for my
program to read, this way I definitely have full access to it and
once I am done with it, Ill delete it. This gave me nothing to print
aswell.
Am I right to deduce that it is always giving me EOF thus this is
having problems.
while ((result = fscanf(readLOG_fp, "%[^\n]\n", ReadLogLine)) != EOF) // Loops through the file till it reaches the end of file
If yes, How do I fix this?? What other ways can I make it read every line. I have seriously exhausted all my ideas on this problem and need some help in this.
Thanks everyone for your help.
Error is very obvious ... you might have over looked it..
You forgot to open the file.
FILE *readLOG_fp;
CString LogPathName;
LogPathName = Source_Folder + "\\serco.log";
readLOG_fp = fopen(LogPathName.GetBuffer());
if(readLOG_fp==NULL)
cout<<"Error: opening file\n";
I'm stuck on problem were I would like to ask for some help:
I have the task to print some files of different types using ShellExecuteEx with the "print" verb and need to guarantee print order of all files. Therefore I use FindFirstPrinterChangeNotification and FindNextPrinterChangeNotification to monitor the events PRINTER_CHANGE_ADD_JOB and PRINTER_CHANGE_DELETE_JOB using two different threads in the background which I start before calling ShellExecuteEx as I don't know anything about the application which will print the files etc. The only thing I know is that I'm the only one printing and which file I print. My solution seems to work well, my program successfully recognizes the event PRINTER_CHANGE_ADD_JOB for my file, I even verify that this event is issued for my file by checking what is give to me as additional info by specifying JOB_NOTIFY_FIELD_DOCUMENT.
The problem now is with the event PRINTER_CHANGE_DELETE_JOB, where I don't get any addition info about the print job, though my logic is exactly the same for both events: I've written one generic thread function which simply gets executed with the event it is used for. My thread is recognizing the PRINTER_CHANGE_DELETE_JOB event, but on each call to FindNextPrinterChangeNotification whenever this event occured I don't get any addition data in ppPrinterNotifyInfo. This works for the start event, though, I verified using my logs and the debugger. But with PRINTER_CHANGE_DELETE_JOB the only thing I get is NULL.
I already searched the web and there are some similar questions, but most of the time related to VB or simply unanswered. I'm using a C++ project and as my code works for the ADD_JOB-event I don't think I'm doing something completely wrong. But even MSDN doesn't mention this behavior and I would really like to make sure that the DELETE_JOB event is the one for my document, which I can't without any information about the print job. After I get the DELETE_JOB event my code doesn't even recognize other events, which is OK because the print job is done afterwards.
The following is what I think is the relevant notification code:
WORD jobNotifyFields[1] = {JOB_NOTIFY_FIELD_DOCUMENT};
PRINTER_NOTIFY_OPTIONS_TYPE pnot[1] = {JOB_NOTIFY_TYPE, 0, 0, 0, 1, jobNotifyFields};
PRINTER_NOTIFY_OPTIONS pno = {2, 0, 1, pnot};
HANDLE defaultPrinter = PrintWaiter::openDefaultPrinter();
HANDLE changeNotification = FindFirstPrinterChangeNotification( defaultPrinter,
threadArgs->event,
0, &pno);
[...]
DWORD waitResult = WAIT_FAILED;
while ((waitResult = WaitForSingleObject(changeNotification, threadArgs->wfsoTimeout)) == WAIT_OBJECT_0)
{
LOG4CXX_DEBUG(logger, L"Irgendein Druckereignis im Thread zum Warten auf Ereignis " << LogStringConv(threadArgs->event) << L" erkannt.");
[...]
PPRINTER_NOTIFY_INFO notifyInfo = NULL;
DWORD events = 0;
FindNextPrinterChangeNotification(changeNotification, &events, NULL, (LPVOID*) ¬ifyInfo);
if (!(events & threadArgs->event) || !notifyInfo || !notifyInfo->Count)
{
LOG4CXX_DEBUG(logger, L"unpassendes Ereignis " << LogStringConv(events) << L" ignoriert");
FreePrinterNotifyInfo(notifyInfo);
continue;
}
[...]
I would really appreciate if anyone could give some hints on why I don't get any data regarding the print job. Thanks!
https://forums.embarcadero.com/thread.jspa?threadID=86657&stqc=true
Here's what I think is going on:
I observe two events in two different threads for the start and end of each print job. With some debugging and logging I recognized that FindNextPrinterChangeNotification doesn't always return only the two distinct events I've notified for, but some 0-events in general. In those cases FindNextPrinterChangeNotification returns 0 as the events in pdwChange. If I print a simple text file using notepad.exe I only get one event for creation of the print job with value 256 for pdwChange and the data I need in notifyInfo to compare my printed file name against and comparing both succeeds. If I print a pdf file using current Acrobat Reader 11 I get two events, one has pdwChange as 256, but gives something like "local printdatafile" as the name of the print job started, which is obviously not the file I printed. The second event has a pdwChange of 0, but the name of the print job provided in notifyInfo is the file name I used to print. As I use FreePDF for testing pruproses, I think the first printer event is something internal to my special setup.
The notifications for the deletion of a print job create 0 events, too. This time those are sent before FindNextPrinterChangeNotification returns 1024 in pdwChange, and timely very close after the start of the print job. In this case the exactly one generated 0 event contains notifyInfo with a document name which equals the file name I started printing. After the 0 event there's exactly one additional event with pdwChange of 1024, but without any data for notifyInfo.
I think Windows is using some mechanism which provides additional notifications for the same event as 0 events after the initial event has been fired with it's real value the user notified with, e.g. 256 for PRINTER_CHANGE_ADD_JOB. On the other hand it seems that some 0 events are simply fired to provide data for an upcoming event which then gets the real value of e.g. 1024 for PRINTER_CHANGE_DELETE_JOB, but without anymore data because that has already been delivered to the event consumer with a very early 0 event. Something like "Look, there's more for the last events." and "Look, something is going to happen with the data I already provide now." Implementing such an approach my prints now seem to work as expected.
Of course what I wrote doesn't fit to what is documented for FindNextPrinterChangeNotification, but it makes a bit of sense to me. ;-)
You're not checking for overflows or errors.
The documentation for FindNextPrinterChangeNotification says this:
If the PRINTER_NOTIFY_INFO_DISCARDED bit is set in the Flags member of
the PRINTER_NOTIFY_INFO structure, an overflow or error occurred, and
notifications may have been lost. In this case, no additional
notifications will be sent until you make a second
FindNextPrinterChangeNotification call that specifies
PRINTER_NOTIFY_OPTIONS_REFRESH.
You need to check for that flag and do as described above, and you should also be checking the return code from FindNextPrinterChangeNotification.