Wednesday, March 1, 2023

Diary #4 LNK 1169, LNK 2005, EnumWindows Example

Working on a simple menu that looks like the PS4's menu. I got LNK 1169 and LNK 2005, and quickly found the cause/fix:

Why does LNK 1169 (and consequently LNK 2005) happen?

It can be a simple code error like 2 different .cpp files each declaring 'int a;', or it could be a project error where file A and B are both 'Source Files', and file A #include's file B.

My case was B. I'd like to quickly log it for myself to help identify and fix it in the future if it escapes me at that time.

The error in the Error List:

Both files test_app.cpp and ps4_menu_sim.cpp are 'Source Files'
 
The file test_app.cpp including ps4_menu_sim.cpp:


 

The fix: right click the file that is included by the other file in Solution Explorer, and click Remove (then click "Remove", and NOT "Delete" when it asks you whether you want to remove it from the project or permanently delete the file).

By my understanding, all 'Source Files' are included by default and it's only in the 'Source Files' that these double declarations mainly occur? Because multiple files can include other dependency files, such as string.h or iostream.h without error. Guess 'Source Files' is best used for OOP classes and globals.

 To avoid the error in the future: instead of right click -> Add on the Source Files tab, right click -> Add on the Resource Files tab. Or just don't add it and it would also be included perfectly well.

 

Also,  an example of EnumWindows, which needs EnumWindowProc passed to it as the first arg. This example stores the found window handles into a windowEnumerator object. More than the visible windows are found by this method (all 'top-level' windows are found by EnumWindows). EnumWindowProc needs to return false to stop enumerating... I'm not really sure how make it return true until I've enumerated enough without checking for a particular window in EnumWindowProc or using global variables top stop after enumerating a certain amount. Since this code returns true indefinitely, it is therefore unusable. Oh well.

#include <iostream>

#include <Windows.h>

#include <string>

class windowEnumerator{
    int len = 2; // indexes available
public:
    HWND *wins = new HWND[2];
    int used = 0; // indexes used/filled
    windowEnumerator(){}
    ~windowEnumerator(){
        delete[] wins;
    }
    bool expand(){
        len *= 2; // double array size
        HWND *newAry = new HWND[len];
        if (!newAry) return false; // couldn't allocate to heap
        for (int xint = 0; xint < used; xint++) // copy over info from old, small array to new array
            newAry[xint] = wins[xint];
        delete[] wins; // free space allocated for old array
        wins = newAry; // make wins point to new array
        return true;
    }
    void add(HWND hwnd){
        if (used >= len && !expand()) return;
        wins[used] = hwnd;
        used++;
    }
    HWND get(int index){
        return (index < used ? wins[index] : nullptr);
    }
    void clear(){
        for (int xint = 0; xint < used; xint++){
            wins[xint] = nullptr;
        }
        used = 0;
    }
}winEnum;
BOOL CALLBACK EnumWindowProc(HWND hwnd, LPARAM lParam){
    winEnum.add(hwnd);
    return true;
}

int main(){
    // let's try something new: enumerate open windows
    if (EnumWindows(EnumWindowProc, NULL)){
        cout << "Successfully enumerated windows this way." << endl;
        cout << "Count of windows found: " << winEnum.used << endl;
        for (int xint = 0; xint < winEnum.used; xint++){
            // get window title bar name
            const int bufferSize = 1024;
            char textBuffer[bufferSize] = "";
            SendMessageA(winEnum.wins[xint], WM_GETTEXT, (WPARAM)bufferSize, (LPARAM)textBuffer);
            std::string str(textBuffer);

            cout << "[ " << xint << " ] ( " << (int)winEnum.wins[xint] << " ): " << str << endl;
        }
    }
    else{
        cout << "Failed to enumerate windows this way." << endl;
    }
    cout << "enter to quit" << endl;
    system("pause");
    //ps4_menu_sim::startup();
    //ps4_menu_sim::main();
    //ps4_menu_sim::shutdown

return 0;

}

No comments:

Post a Comment

Coding Challenge #54 C++ int to std::string (no stringstream or to_string())

Gets a string from an integer (ejemplo gratis: 123 -> "123") Wanted to come up with my own function for this like 10 years ago ...