So I'm not going to post the entire source to my pack because it's way too long and cluttered (I can barely understand it at this point), so I'll be posting stuff that I had trouble with while making it. Everything is written in Visual C++ 2010 Express. To get it to compile with the threads, press Alt+F7 to open the Project Properties, expand the Configuration Properties menu, expand the C/C++ menu, select General, and change the Command Language RunTime Support from /clr: pure to /clr. Then, select Command Line, and put /Gd in the Additional Options and hit OK. Then, include
Code:
using namepsace System;
using namespace System::Threading
That will let you use threads. Pictures for anyone confused (they are out of order. Correct order is #2 then #3 then #1): https://imgur.com/Drz2ezT,HxgPc5f,v6JZOyI#0
I couldn't get the normal SendInput() method to work, so I just used the keybd_event() function which works fine. SendInput() for the clicking worked though.
Code:
void Generate_Key(int key){
keybd_event(key, 0, 0, 0);
Sleep(1);
keybd_event(key, 0, KEYEVENTF_KEYUP, 0);
}
My mouse hook function for the scroll wheel.
Code:
LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) { //hook for mouse wheel
if (nCode >= 0) {
if (wParam == WM_MOUSEWHEEL){
bool cont = true; //this bit stops the mouse wheel from switching the weapon faster than AVA can
duration = (clock() - start ) / (float) CLOCKS_PER_SEC;
if(duration < 0.01){
cont = false;
}
else{
start = -1;
}
if(cont){
if(start == -1){
start = clock();
} //bit mentioned above ends here
MSLLHOOKSTRUCT *pMhs = (MSLLHOOKSTRUCT *)lParam;
short zDelta = HIWORD(pMhs->mouseData);
if(duration > 0.05){ //bit also here, more effective than above, but I'm too lazy to remove above
if(zDelta < 0){
if(wep_spot < 4){
wep_spot++;
}
else{
wep_spot = 1;
}
}
else if(zDelta > 0){
if(wep_spot == 1){
wep_spot = 4;
}
else{
wep_spot--;
}
}
}
}
}
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
Because the GUI has its own event loop, you need to make a thread to run the GUI.
Code:
DWORD WINAPI form_run(void* ignore){
Form1^ form = gcnew Form1(); //create a GUI form object
ThreadStart^ state_del = gcnew ThreadStart( form, &MacroPack::Form1::change_macro_state ); //thread to check for input and change GUI text
Thread^ state_thread = gcnew Thread(state_del); //make the thread
state_thread->Start(); //start the thread
Application::Run(form); //run the GUI
done = true; //once the GUI finishes, this bool will alert the other threads to close
}
That's how you create the thread to run the GUI.
Code:
int main(){
DWORD form_thread;
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&form_run, NULL, 0, &form_thread);
}
Note that everything above was in the main.cpp file. It uses stuff from the header file, which contains the actual class for the GUI.
Next is header file stuff.
Because you are not allowed to touch anything the GUI thread is running without being in the GUI thread (program crashes with a "cross-threading" error), you have to use something called delegates. I don't understand delegates very well, but from what I know, they tell a thread to run a function, which pretty much allows you to inject into the thread. Here's how to make a delegate and get it to change the text of a label on the GUI from another thread:
Code:
public delegate System::Void qswitch_delegate(); //define the delegate function name
qswitch_delegate^ qswitch_del; //create the delegate variable
qswitch_del = gcnew qswitch_delegate(this, &MacroPack::Form1::qswitch_state); //set the delegate variable to the function you want
this->label13->Invoke(qswitch_del); //get the item on the GUI to call the function itself
qswitch_state sets the text of label13 to whatever it needs to be set to. I realize the delegates are kind of odd, if anyone is confused by them and wants a better explanation/ example send me a private message (or if you can't, post in this thread) and I'll help you out. Asking for code to be copy/pasted will not help you, so don't do it. Asking for an explanation on code to be copy/pasted is fine, you can learn from that.
That's everything that I feel needs to be posted. The rest of the code is really sewn together, it looks awful, but if anyone wants to see any other parts (or the whole thing if you think you can handle it), post here or send me a pm and I'll send what you want along with an explanation of how it works. I'm happy to answer any question about the code.