how do i make this so everything can use it? C++ - c++

im somewhat new to c++ so i don't know how to do this but my main point in recoding this is to incress the speed of my program, i have been coding a project
and my code is:
HWND hWnd = FindWindow(NULL, L"*window's name*");
DWORD th32ProcId;
HANDLE hProc;
GetWindowThreadProcessId(hWnd, &th32ProcId);
hProc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, 0, th32ProcId);
so i have about 20 functions that all use that at the start of each time i run them and the value will never change so is there some way i can declare and then set it at the value of what it finds?
my code is set up like this
one main file int main() and it's just set on a loop and it keeps retesting and calls the other functions and everything else is in a void name() and i have 2 int name()
im using VC++ 2008.
edit
no :| i just want a way i can share thoses values with all of the program.

If I understand your question correctly you want to implement some kind of caching. That would be fine and you can create a cahe with an std::map.
You would probably have something like:
std::map<std::string, HANDLE> cacheMap;
You can then check the cacheMap to see if a result exists. It if does exist you don't need to call the function, if it does not exist you would then call the function and add the result to your map.

Related

How do i write and call this type

I'm having a problem here and the problem is that the hService is 0
I'm having or creating the Windows Form application and I've put:
HSERVICE hService=0;
BOOL fSuccess=EXIT_SUCCESS;
if(Wfs_Startup())
{
// This returns a successful startup even if I write something here
// to be displayed by a textbox it does. That means the Startup is ok.
if(Wfs_Open(&hService))
{
// What ever I put here doesn't show on a textbox and the application jumps to
// the exception of this block which means there's a problem here, at first I
// thought it was because of no corresponding logical name on a registry but what
// I found out was that if I check below the Startup block and check the hService
// it's 0 so it doesn't receive the correct data from the startup.
}
}
so I took that from "I will say" a function that is written like this:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdDLine,
int nShowCmd)
{
//THE CODE BLOCK IS THE SAME AS THE ABOVE THAT GOES HERE.
}
So I took the inside code block to FormLoad but this is giving me the above mentioned problem, can I have both the FormLoad and the WinMain? Because I tried to have the WinMain but there was an error I think it said there can't be two Main or something like that. Also how can I call the WinMain within FormLoad as when I tried it required the arguments to be included and the main problem is that I can't add the arguments in a FormLoad.
any suggestion to how can I resolve this problem?
Sorry but don't know the easy way to explain this. But keep in mind the problem that the hService returns 0.
Ok just to simplify this question:
How to call this type of Function that's starts with HRESULT at the beginning please check above. What I want is to fire that Function, I think that will simplify this even though there's another question about calling it on FormLoad but first I want to know how to call/fire that kind of Function?
The problem is that the IDE says I can not have the int WinMain on Windows Form because its already has something like that but when I'm working with command its works. I can have WinMain and Main but can't have WinMain and FormLoad not inside but within the project or page. To understand please create a Windows Form App and try typing the int WinMain code you will see what's my problem here.
I have found the great tutorial that gives a good reason why I'm getting this problem:
https://msdn.microsoft.com/en-us/library/bb384843.aspx

C++ Creating Window in other cpp files (not in WinMain)

I have a function that is located in a different cpp file than WinMain is, and when called will create a window. However the windows class for that new window was declared and registered inside of WinMain. Now, when I create the window in the separate function, I am forced to redeclare the 2nd and 3rd variable of the CreateWindowEx function:
_In_opt_ LPCTSTR lpClassName,
_In_opt_ LPCTSTR lpWindowName,
because the location of the function that is actually doing the creating doesn't have access to those variables that were created in WinMain. Now... my doubt is, is my program actually using the window class I registered in WinMain? For all I know, redeclaring these variables, and creating the function far away from the WinMain function could have caused the compiler to adopt some other standard window class. So, is my program actually using the window class I registered in WinMain?
Edited: giving slightly more code
//+++++++++++++++++++++++++++++++++++++cpp file with win main:
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
...//previous code made the main window of the program and so forth
const char g_szClassName2[] = "windowClass2";//name of the window class
WNDCLASSEX winClass2;
HWND invisHWnd;
winClass2.cbSize = sizeof(WNDCLASSEX);
winClass2.style = 0;
winClass2.lpfnWndProc = WndProcedure2;
winClass2.cbClsExtra = 0;
winClass2.cbWndExtra = 0;
winClass2.hInstance = hInstance;
winClass2.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winClass2.hCursor = LoadCursor(NULL, IDC_ARROW);
winClass2.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
winClass2.lpszMenuName = NULL;
winClass2.lpszClassName = g_szClassName2;
winClass2.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&winClass2);
... //other code irrelevant to issue
}
//+++++++++++++++++++++++++++++++++++++other cpp file:
void otherCppFile::creatingWindow()
{
const char g_szClassName2[] = "windowClass2";//name of the window class
const char WndName2[] = "winClass2";//name of the window class
HWND windowHandle = CreateWindowEx(0,
g_szClassName2,
WndName2,
WS_OVERLAPPEDWINDOW,
0,
0,
800,
500,
NULL,
NULL,
NULL,
NULL);
}
Is this last function using the window class registered in WinMain even though it is not located in WinMain and some of the variables are redeclared in the function?
The whole point of registering a window class is so that it is unique and you can use it whenever you need to. When you register a window class using the RegisterClass[Ex] function, you have two options for identifying it:
The window class name (a string) that you passed into the function.
An ATOM (an integer value) that is returned by the function.
In 99.9% of cases, you'll forget about the ATOM and just use the string. You need the string to create the window class, so you might as well just keep up with the string and use it to create windows of that class.
Technically, what you're doing is okay, then. You have multiple variables, but they all contain exactly the same string value, so everything is working properly. But that's a maintenance nightmare, and also violates the DRY (don't repeat yourself) rule. What if you wanted to change the name of your window class? You'd have to find every file that declared it and make sure that you updated it. Then you'd have to wait forever for your entire project to recompile, because you've touched large numbers of files. No good.
Instead, you want to declare this variable at global scope, making it available in every file of your project that creates windows. Put it in a common header file that you're going to include in all of your code files, or make a separate Window.h header or something of that nature and include it where appropriate.
Do make sure that this window class name is declared as a constant. There is no reason it should ever be modified during the execution of your application.
If you're struggling with declaring and/or using global constants in C++, you might check the answers to this question or do a search of your own on Stack Overflow. This part is not unique to Windows programming; it is just basic C++.
Of course, you'll often hear that global variables are bad. That's true enough. The code that you're writing isn't really C++. It is C. The Windows API is a C API, so it naturally leads you into writing C code in C++. If you want to really write C++ code, you'll need to find (or write your own) C++ wrapper around the C-based Windows API. For example, you'd write a class that represents windows, and that class would contain a static class-level constant that holds the name of your window class. The class would be responsible for creating all new windows, so you wouldn't need to scatter that information or those implementation details across multiple code files.
As far as the window name, this is completely different. Windows doesn't use it to identify your window. In fact, it is a completely optional parameter for the CreateWindow[Ex] function. You don't even have to give the window a name. This is actually the name that appears in the window's title bar. It is used by the user to identify the window. As such, it often needs to be localized and should be stored in your project's resources file, not in the source code. Use the LoadString function to load strings from your project's resource file. You can do this dynamically whenever you create a window: just load the string you want to use as the caption for that particular window.

Problems with PostMessage from C++ .dll to Delphi Forms application

I have Windows Forms Application written on Delphi 7 and C++ .dll written using MFC.
Currently I'm trying to implement basic message posting from .dll to main executable to show user calculation process on progressbar, but several problems were faced.
Let me describe my approach first. I register simple message in my Delphi application like:
WM_MSG := RegisterWindowMessage('WM_MSG');
and do the same at the library part:
UINT nMsgID = RegisterWindowMessage(_T("WM_MSG"));
This is OK: I can see same values on both sides when debugging.
My library function looks like this (just a dummy example to test progress bar):
extern "C" __declspec(dllexport) int MyFunction() {
UINT nMsgID = RegisterWindowMessage(_T("WM_MSG"));
HWND hWnd = FindWindow(NULL, "Form1");
if (hWnd > 0)
for (int i = 0; i < 100000; i++) {
int param = ceil(100 * (double) i / (double) 100000);
PostMessage(hWnd, nMsgID, param, NULL);
}
return 1;
}
Executable OnMessage event:
procedure TForm1.OnMessageEvent(var Msg: tagMSG; var Handled: Boolean);
begin
Handled := True;
if Msg.message = WM_MSG then
ProgressBar1.Position := Msg.wParam
else Handled := False;
end;
C++ function call from executable:
procedure TMyFunctionDLL.Execute;
var
i: Integer;
tHWND: HWND;
begin
tHWND := FindWindow(nil, 'mainF');
i := Func;
end;
First problem is that tHWND and hWnd variables values are inexplicably different. After some research I've discovered 3 situations:
1. Negative or positive huge hWnd
2. Zero hWnd
3. Undefined ('???')
In all cases variable hWnd is marked as unused and I don't know what does that mean. The most interesting thing is that code DOES work if I test it in very simple Delphi form (with only one unit). That simple Delphi form works well with my real C++ .dll code where real data is calculated. But when I use my general Delphi application (many units but still one form) it seems main application OnMessage event doesn't catch any events from C++ dll.
So, there are 2 questions:
1. why are hWnd values are always different and why are they 'unused'?
2. how can I force my main application to work correctly with progressbar?
I've been using different approaches to resolve this. Such as passing Application.Handle or Form1.Handle as function parameter to C++ library. None of them worked not even saying about parameter value changed while passing (I guess that should be separate question). Also I've tried using ::FindWindow() and ::PostMessage() instead of FindWindow() and PostMessage() (what is difference between them?), that didn't helped either. I'm trying to improve situtuation for whole day already but have no idea how to solve it. Help me with any ideas please.
In addition to what others have stated, a better design would be to have the EXE pass its HWND into the DLL directly, then the DLL does not have to go hunting for it. This has the added benefit that the EXE can then decide which HWND the DLL should post its messages to. I would use AllocateHWnd() to create a dedicated window for that.
Try this:
UINT nMsgID = RegisterWindowMessage(_T("WM_MSG"));
extern "C" __declspec(dllexport) int __stdcall MyFunction(HWND hWnd) {
if ((nMsgID != 0) && (hWnd != NULL)) {
for (int i = 0; i < 100000; i++) {
int param = ceil(100 * (double) i / (double) 100000);
PostMessage(hWnd, nMsgID, param, 0);
}
}
return 1;
}
.
unit Unit1;
interface
...
var
DllWnd: HWND = 0;
implementation
var
WM_MSG: UINT = 0;
procedure TForm1.FormCreate(Sender: TObject);
begin
DllWnd := AllocateHWnd(DllWndProc);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if DllWnd <> 0 then
begin
DeallocateHWnd(DllWnd);
DllWnd := 0;
end;
end;
procedure TForm1.DllWndProc(var Message: TMessage);
begin
if (Message.Msg = WM_MSG) and (WM_MSG <> 0) then
ProgressBar1.Position := Message.WParam
else
Message.Result := DefWindowProc(DllWnd, Message.Msg, Message.WParam, Message.LParam);
end;
...
initialization
WM_MSG := RegisterWindowMessage('WM_MSG');
end.
.
uses
Unit1;
function DllFunc(Wnd: HWND): Integer; stdcall; external 'My.dll' name 'MyFunction';
procedure TMyFunctionDLL.Execute;
var
i: Integer;
begin
i := DllFunc(DllWnd);
end;
Results from FindWindow can either be zero or non-zero. Handle values don't lie on the number line. They're just distinct values, so it makes no sense to apply inequality operators to them. Put another way, handle values can appear to be negative, so don't assume that valid handles will always be greater than zero.
If the window-handle values don't match, then it's no wonder nothing else works. You're in no position to be debugging the functionality of your messages since you're not even sure you're sending them to the right window. Focus on fixing that first.
Only use FindWindow as a last resort. It has offers no facility for detecting when there are multiple windows that fit your search criteria. It always returns exactly one result. When possible, avoid searching at all. Instead, tell the sender exactly what window to send messages to. You say you tried this and failed, but I urge you to pursue that avenue some more. The problem you had was probably a mismatched calling convention. Make sure both the DLL and the host application use stdcall.
Once you're sure you're sending messages to the right window, then you can worry about why your messages aren't operating the progress bar correctly. I can see at least two reasons:
While the DLL function is running, your main program, which called the DLL, is not. It's waiting for the DLL code to return. That means your main program is not handling any messages. The DLL is posting a bunch of messages, but they're not getting handled yet. They won't get handled until the program gets back to its message loop.
The default size of the Windows message queue is 10,000. You're posting 10 times that many messages to the queue and not handling any before you stop, so even if the queue was completely empty before you started (which is unlikely, since you're probably triggering this functionality from keyboard or mouse input), you'd only get one-tenth the messages. When the queue is full, PostMessage just discards the message. And since the value you're sending with the message is an integer between 0 and 100, it's rather pointless to send 100,000 of them when only 101 of them will hold meaningful information.
If identical calls to FindWindow return different windows then you must have multiple windows with the name Form1. Try giving these different windows different names so that they can be uniquely identified.
The unused question is a little unclear. Perhaps you mean that the compiler has noticed that the value assigned to tHWND is never used and is thus pointless.
I would make a final comment that the question is imprecise and this is probably part of your problem. For example you say that all the variables are unused but we have no clear idea what you mean. You will have more success in debugging if you are more precise and methodical.
Allright, seems I've resolved the problem...
I tried Remy's proposal to declare exported function
function MyFunction (fHWND: HWND): Integer; cdecl; external 'My.dll'
with cdecl calling convention as David adviced. My previous function declaration looked like this
TMyFunction = function (fHWND: HWND): Integer;
and I suppose that was the problem. Thank you all for your help!
P.S. Now, how can I close the question?

Get PID from ShellExecute

I am launching a process from ShellExecuteEx, and I really need to get the ProcessID (It's part of the requirement of this class).
Somehow all the important SHELLEXECUTEINFO returns null.
So for example if I use this code:
exInfo.lpVerb = "open";
exInfo.lpFile = "C:\\Windows\\system32\\cmd.exe";
exInfo.nShow = 5;
ShellExecuteExA(exInfo);
It launched CMD.exe. But now I need to get it's PID.
exInfo.hwnd is returning 0, and exInfo.hProcess is returning null.
Is this normal behaviour?
I don't really want to resort to using CreateProcess(), because my function should also be able to launch documents like "C:\doc1.docx". This is just a method, in which I cannot predict what is going to be launched (So I cannot know the window title/classname from beforehand, get the hWnd from there and then get the PID).
Could somebody kindly point out my mistake? Thanks.
You need to set a flag (SEE_MASK_NOCLOSEPROCESS) in exInfo.fMask

How to write simple background thread in CWorkerThread

I'm trying to asynchronously run function in my add-on for Internet Explorer (I'm writing BHO in VC++). As suggested here I'm trying to use CWorkerThread.
I've been trying to figure it out for hours but still have no idea how to do it. I don't have much experience in ATL. The lack of a good documentations or tutorials on Internet is killing me.
I'm creating class by Add->Class and choosing ATL Simple Object (that's how you add classed to ATL project right?). But how to implement this IWorkerThreadClient? I thought that choosing Add->Implement Interface in Class View would be good but there is no IWorkerThreadClient on the list.
I think I don't know ATL or COM enaugh but can't find good resource for learning this (esspessialy newest ATL7).
I even tried winapi CreateThread approach but it isn't working. I'm passing this class pointer to run static method but something is corrupting with memory later. Nevertheless if It had worked I still would rather use something else than CreateThread.
Right now I have something like this. In OnDocumentComplete there's RemoveImages(sptmlDoc) and I just want to run it asynchronously.
EDIT: What I did with CreateThread:
I tried running RemoveImages function (from here) asynchronously. I created static function in my class with signature like here. RemoveImages has parameter so I copied it to a member of a class:
if (htmlDoc2 != NULL)
{
m_tmpHtmlDocument2 = htmlDoc2;
m_hThread = CreateThread( NULL, 0, MyThreadFunction, this, 0, &m_threadId);
}
and MyThreadFunction:
static DWORD WINAPI MyThreadFunction( LPVOID lpParam )
{
CHelloWorldBHO* myClass = (CHelloWorldBHO*)lpParam;
myClass->RemoveImages(myClass->m_tmpHtmlDocument2);
return 0;
}
I get "Unhandled exception at 0x60c0da05 in iexplore.exe: 0xC0000005: Access violation reading location 0x000001b8." here in the bold line:
void CHelloWorldBHO::DontDisplayElement(CComPtr htmlElement)
{
CComPtr style;
HRESULT hr = htmlElement->get_style(&style);
if (hr == S_OK && style != NULL)
{
static const CComBSTR strNone(L"none");
style->put_display(strNone);
}
}
Your performing a naughty by trying to use a COM handle allocated in 1 thread in another. BHO environment is STA (Single Threaded Apartment) so you should be marshalling the m_tmpHtmlDocument2 object for use in your thread.
Experiance has shown that in some cases IE may let you get away with passing the Browser com object from 1 thread to another and then getting the document and elements afterwards may work. This is entirely unreliable.
Depending on IE 6/7/8 you will have different target threads to execute your actions on, thinking at the levels of per security level/frame/tab/window. basically any time IE creates a new 'Site'
Also to prevent your app from holding the pages active even after navigation away from the page, in FireFox you would use an nsWeakPointer<> , I've never found the equivelant in IE.
Suggestion: Perhaps instead of marshalling com to another thread because your interaction with the page is slow, trying to improve the way you interact with the page and improve performance in process might be a better aim.
Here is an outline using the CThreadPool which will queue up requests, and then execute them when the pool has space.
I use pvWorkerParam to tie the threads back to the site.
I have different types of ActionRequests, you could of course simplify and just pass null for the request.
Note: This doesn't resolve marshalling issues you already have
class ActionRequest{
DontDisplayElement();// define your do stuff in here
};
class ScriptWorker
{
public:
ScriptWorker(void);
virtual ~ScriptWorker(void);
public:
BOOL Initialize(void* pvWorkerParam);
void Execute(ActionRequest *request, void* pvWorkerParam, OVERLAPPED* pOverlapped){
try{
std::auto_ptr<ActionRequest> cleanupRequest(request);
request.DontDisplayElement();
} catch(...) {}
}
void Terminate(void* pvWorkerParam);
private:
boolean m_bCoUninit;
};
Site{
CThreadPool<ScriptWorker> m_scriptWorkerThread;
Site() {
void *pvWorkerParam = this;// or whatever you want to have passed to every script worker and execute in the pool.
m_scriptWorkerThread.Initialize( pvWorkerParam, 1 );
}
OnDocumentComplete() {
m_scriptWorkerThread.QueueRequest( new ActionRequest() );
}
}
and sptmlDoc - is it an IHTMLDocumet* ?
IWorkerThreadClient - never heard of it
"I even tried winapi CreateThread approach but it isn't working. I'm passing this class pointer to run static method but something is corrupting with memomory later"
Keeping it simple is the best design pattern of them all. So stick with CreateThread unless you have good reasons not to. Now, my guess is that the crash occurs because of sptmlDoc being passed to the thread for later processing. The thing is such pointers are only valid from the BeforeNavigate event until DocumentComplete event. Try to do that processing on the spot (inside your event handler) and see if it stil crashes. Some code posting would help too