How to rename a printer in C++ on Windows? - c++

In WinSpool.h I can enumerate all the printers using the EnumPrinters function, but I cannot find out how to rename an existing printer?

You can use the SetPrinter function to rename a printer.
You would set the Level parameter to 2 and the pPrinter parameter would point to a PRINTER_INFO_2 structure. The PRINTER_INFO_2::pPrinterName field lets you change the printer name.
Note that the docs for SetPrinter say:
To modify the current printer settings, call the GetPrinter function
to retrieve the current settings into a PRINTER_INFO_2 structure,
modify the members of that structure as necessary, and then call
SetPrinter.
So you would need to call GetPrinter with a properly initialized structure first, before modifying the name and calling SetPrinter.

Related

Firemonkey: How to iterate through all forms in the application using TScreen.Forms

I am attempting to iterate through the forms I have open in my application. I have found the documentation for FMX.Forms.TScreen.Forms, which looks like it can be used to accomplish my goal. However, I am confused on how I am supposed to use it.
At first I tried this in a function within my form's CPP file:
ShowMessage( Forms::TScreen::FormCount );
This produced the error 'Member TScreen::FormCount cannot be used without an object'
I figured that to mean that I need to attempt to access this property from my form, or from the global Application variable. I tried both
this->Forms...
Application->Forms...
and
this->TScreen...
Application->TScreen...
However, neither Forms nor TScreen exist within either of these objects.
How do I go about accessing Forms.TScreen.Forms?
The error gives you a clue:
Member TScreen::FormCount cannot be used without an object
TScreen is a class, not an object. FormCount is not a static member of the class, so you need an object instance of the TScreen class. And such an object is provided for you - the global Screen object:
ShowMessage( Screen->FormCount );
This is stated in the documentation:
FMX.Forms.TScreen
There is a global variable, Screen, of type TScreen, which is instantiated for use by any application with a GUI. Use Screen to obtain information about the current state of the screen in an application.
FMX.Forms.Screen
extern DELPHI_PACKAGE TScreen* Screen;
Here's what works well:
ShowMessage(Screen->FormCount);
Screen is a global object, like Application. The compiler said that FormCount is not static method or smth.

C++ how to get folders and files names from virtual device?

How to get all folders and files names in virtual device plugged to pc?
In C++;
I have problem because the virtual device not have a letter like local disc;
Path started like this "Computer\SUPRA_M727G\Internal storage"
You have to use Shell interfaces, namely IShellFolder and IEnumIDList.
To get an IShellFolder for the "Internal storage" folder, you can either:
Use SHGetDesktopFolder() to get an IShellFolder for the root of the Shell namespace, then pass the "Computer\SUPRA_M727G\Internal storage" string to its IShellFolder::ParseDisplayName() method to get an absolute ITEMIDLIST that you can pass to its IShellFolder::BindToObject() method.
Use SHParseDisplayName() or ILCreateFromPath() to convert the "Computer\SUPRA_M727G\Internal storage" string into an absolute ITEMIDLIST that you can pass to SHBindToObject() with its psf parameter set to NULL.
Either way, once you have an IShellFolder for the storage folder, you can use its IShellFolder::EnumObjects() method to get an IEnumIDList for enumerating its files and subfolders. The enumeration will give you a relative ITEMIDLIST for each item. To retrieve each item's name as a string, pass each ITEMIDLIST to its IShellFolder::GetDisplayNameOf() method, and then pass the returned STRRET to one of the StrRetTo...() functions (StrRetToBSTR(), StrRetToBuf(), or StrRetToStr()).
Refer to MSDN for more details:
Introduction to the Shell Namespace
Navigating the Shell Namespace

Can I call C++ code from Progress OpenEdge ABL?

Is it possible to execute C++ code from within Progress ABL?
Specifically, I am looking to use the function SHGetKnownFolderPath (documentation here) to determine the location of the "Documents" folder on a Windows 7 machine that has the documents folder redirected to another location.
Or, is there an alternative way to determine this information without resorting to checking a registry key?
You can call external shared libraries and DLLs.
http://documentation.progress.com/output/OpenEdge113/pdfs/dvpin/dvpin.pdf
Section 3 "External Interfaces" is what you are looking for.
This http://dbappraise.com/ppt/shlib.pptx might also be helpful.
C++ is often problematic due to the way it names things. You might be better off building a "shim" using plain old C to bridge between OpenEdge and C++
Callling Windows system functions is usually easy though. Something like:
procedure SHGetKnownFolderPath external "pathToLibrary":
define parameter a as someType.
define parameter b as someType.
define return parameter x as someType.
end.
Check the "Programming Interfaces" document, "External Program Interfaces" section.
Also, some versions of ABL also support direct .NET calls as an option.
I was able to get this working in 10.2B after consulting some sources:
The C# solution, for a working example: https://stackoverflow.com/a/21953690/763102
Win32 OpenEdge samples, for translation examples: http://www.oehive.org/book/export/html/385.html
The difficult part for SHGetKnownFolderPath is the rfid parameter which needs to be passed by reference. C# has the annotation [System.Runtime.InteropServices.MarshalAs(UnmanagedType.LPStruct)] or the ref keyword. I couldn't figure out how to pass a reference of System.Guid due to Progress OpenEdge's limitations of external procedure parameter datatypes, so I performed a bytewise copy of a .NET Guid and passed that via MEMPTR. I apologize for leaning so heavily on .NET here.
Here is a working example that gets the provided known folder GUID, plus usage to get the Documents folder:
PROCEDURE SHGetKnownFolderPath EXTERNAL "shell32.dll":
DEFINE INPUT PARAMETER rfid AS MEMPTR.
DEFINE INPUT PARAMETER dwFlags AS UNSIGNED-LONG.
DEFINE INPUT PARAMETER hToken AS LONG.
DEFINE OUTPUT PARAMETER ppszPath AS LONG.
DEFINE RETURN PARAMETER result AS LONG.
END PROCEDURE.
FUNCTION prepareGuidPointer RETURNS MEMPTR(
pGuid AS System.Guid):
DEFINE VARIABLE lGuidBytes AS INTEGER EXTENT.
ASSIGN lGuidBytes = pGuid:ToByteArray().
DEFINE VARIABLE lGuidPointer AS MEMPTR NO-UNDO.
SET-SIZE(lGuidPointer) = EXTENT(lGuidBytes).
DEFINE VARIABLE ii AS INTEGER NO-UNDO.
DO ii = 1 TO EXTENT(lGuidBytes):
PUT-BYTE(lGuidPointer, ii) = lGuidBytes[ii].
END.
RETURN lGuidPointer.
END FUNCTION.
FUNCTION deallocatePointer RETURNS INT64(
pPointer AS MEMPTR):
SET-SIZE(pPointer) = 0.
RETURN GET-SIZE(pPointer).
END FUNCTION.
FUNCTION GetKnownFolderPath RETURNS CHARACTER(
pGuidString AS CHARACTER):
DEFINE VARIABLE lDontVerifyFolderFlag AS INT64 NO-UNDO
INITIAL 16384. /* 0x4000 */
DEFINE VARIABLE lUseDefaultUser AS INTEGER NO-UNDO
INITIAL 0.
DEFINE VARIABLE lGuidPointer AS MEMPTR NO-UNDO.
ASSIGN lGuidPointer = prepareGuidPointer( NEW System.Guid(pGuidString) ).
DEFINE VARIABLE lResult AS INTEGER NO-UNDO.
DEFINE VARIABLE lPathResponse AS INTEGER NO-UNDO.
RUN SHGetKnownFolderPath(
INPUT lGuidPointer,
INPUT lDontVerifyFolderFlag,
INPUT lUseDefaultUser,
OUTPUT lPathResponse,
OUTPUT lResult).
deallocatePointer(lGuidPointer).
IF lResult GE 0 THEN
DO:
DEFINE VARIABLE lStringPath AS CHARACTER NO-UNDO.
DEFINE VARIABLE lPathPointer AS System.IntPtr NO-UNDO.
ASSIGN lPathPointer = NEW System.IntPtr(lPathResponse).
ASSIGN lStringPath =
System.Runtime.InteropServices.Marshal:PtrToStringUni(lPathPointer).
System.Runtime.InteropServices.Marshal:FreeCoTaskMem(lPathPointer).
RETURN lStringPath.
END.
ELSE
UNDO, THROW NEW System.Runtime.InteropServices.ExternalException(
"Unable to retrieve the known folder path. It may not be available on this system.",
lResult).
END FUNCTION.
DEFINE VARIABLE lDocumentsGuidString AS CHARACTER NO-UNDO
INITIAL "~{FDD39AD0-238F-46AF-ADB4-6C85480369C7}".
MESSAGE GetKnownFolderPath(lDocumentsGuidString)
VIEW-AS ALERT-BOX.

Reading DEVMODE structure from Registry

I am working on a project where I need to program for print operations from device.
It has WIN CE 6.0. I am using Visual Studio 2005 (MFC).
The printer can be any PCL-compatible printer.
Currently, to get printer DC, I am using CreateDC().
hPrinterDC = CreateDC(L"PCL.DLL", L"Any Name", L"LPT1", NULL);
Using this call I am able to print successfully.
Here I am passing DEVMODE specific input parameter as NULL. But for having finer control over these print operations, I need to pass DEVMODE information to CreateDC().
For that I am planning to make a call to CreateDC() as specified above to generate DEVMODE specific information in the registry. I can then read this DEVMODE data from registry into local variable, modify only necessary fields of this variable, and pass this variable to CreateDC() to get printer DC for actual print operations to follow.
I am avoiding direct initialization of DEVMODE struct, as I don't have enough information about certain fields of DEVMODE e.g. dmDriverExtra.
I need to know how can I safely read a struct like DEVMODE from registry? Any relative example will be really helpful.
Kind Regards,
Aftab
This is ancient, but just in case someone finds this still useful.
The DEVMODE contains private and public area, so allocating it with size equal to sizeof(DEVMODE) will exclude some settings. Proper way to initialize the DEVMODE is to query its default state using DocumentProperties() function. It returns number of bytes required when last parameter is set to zero.

Is there an API to get the original variable values defined in OS

In the Windows System Properties | Environment Variables, there is a variable "AppStatus=status1".
There is an exe named MyApp.exe. In the implementation it changes the variable with the code.
int ret = putenv("AppStatus=status2"); // Change the environment variable.
If use API char * pStatus = getenv("AppStatus");, the returned value is "status2".
What I want to get is the original value defined in the OS ("AppStatus=status1") not in the process block. To implement this I can query the registry key
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\Path.
But it should be better if there is an API that supports it. Is anybody aware of it?
Just call GetEnvironmentVariable(). It works on the process state as maintained by Windows, not the CRT state modified by putenv().