0

i am building program that ask for a file and then filter it to what the user want (black and white, smooth and so on). i use in opencv for the filter and windows.h for the GUI. but for loading a picture to the Pimage in opencv - i need the image full path. so of curse i can just give the user textbox and say to him write the all path, but it will be really nasty programm ...

Then i remember in Photoshop and his nice file dialog that allowed me to load file without writing the all path.

Quick search in google give me the OPENFILENAME struct, But when i try to use the function that give me the name of the file:

if(GetOpenFileName(&ofn))
    {
        printf("File path: %s", szFileName)
    }

It always give me this error in the console:

undefined reference to `GetOpenFileNameA@4'
collect2: ld returned 1 exit status

Sucks!

So to sum up, I just want nice code that i will press on the "load" button, the file dialog will open, and the full path of the file will print to the screen. this is my code so far (my and my good good friend Code Blocks):

#if defined(UNICODE) && !defined(_UNICODE)
    #define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
    #define UNICODE
#endif

#include <tchar.h>
#include <windows.h>
#define HEIGHT 500
#define WIDTH 500
/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
HWND button_1;
/*  Make the class name into a global variable  */
TCHAR szClassName[ ] = _T("windows form");

int WINAPI WinMain (HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nCmdShow)
{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default colour as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           _T("windows form"),       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           WIDTH,                 /* The programs width */
           HEIGHT,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nCmdShow);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}


/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  /* handle the messages */
    {
        case WM_CREATE:
            button_1 = CreateWindow("BUTTON",
                "Open file", WS_VISIBLE | WS_CHILD | WS_BORDER,
                WIDTH/2, HEIGHT/2, 100, 40, hwnd, (HMENU) 1, NULL, NULL);
                break;
        case WM_DESTROY:
            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}
lurker
  • 56,987
  • 9
  • 69
  • 103
Mark green
  • 43
  • 9
  • The error message means it can't find the `GetOpenFileNameA` function in any module or library you're linking with. Why are you calling `GetOpenFileNameA` and not [`GetOpenFileName`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646927(v=vs.85).aspx)? And are you linking with the correct Windows API library? – lurker Jun 30 '17 at 11:20
  • i use in GetOpenFileName and i still get the same error: (.text+0x12d): undefined reference to `GetOpenFileNameA@4'. i just include windows.h not link nothing. – Mark green Jun 30 '17 at 11:26
  • You need to link with `Comdlg32.lib`. – Jabberwocky Jun 30 '17 at 11:27
  • 1
    See the rest of my first comment. You must not be linking with the correct library. That's what the error means. – lurker Jun 30 '17 at 11:27
  • 1
    A header file, like `windows.h`, just gives the compiler the *declaration* of the external function so that it understands the arguments, etc. The header file does not *define* the function. For that, you must include the source to compile, or you must link with a library that contains the function already compiled. In this case, as @MichaelWalz indicates, `Comdlg32.lib`. For external library functions, header files and library files go hand-in-hand. You need the header for compiling, and the library file for linking. – lurker Jun 30 '17 at 12:04
  • so what file i need to include? i need to download something/add to the path? – Mark green Jun 30 '17 at 12:33
  • Possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – IInspectable Jun 30 '17 at 13:35
  • @lurker: Almost correct. But Microsoft's compiler allows you to pass linker options through source/header files (e.g. `#pragma comment(lib, ...)`, and some headers in the Windows SDK do (not this one, though). – IInspectable Jun 30 '17 at 13:38
  • @Markgreen check your compiler linker options, etc. You shouldn't have to download anything. If you have a legitimate installation of development tools, the common Windows library files you need should be available. – lurker Jun 30 '17 at 13:47

1 Answers1

1

You simply cannot use GetOpenFileName() without defining the OPENFILENAME structure.

LPSTR filebuff = new char[256];
OPENFILENAME open = { 0 };
            open.lStructSize = sizeof(OPENFILENAME);
            open.hwndOwner = window; //Handle to the parent window
            open.lpstrFilter = "Image Files(.jpg|.png|.bmp|.jpeg)\0*.jpg;*.png;*.bmp;*.jpeg\0\0";
            open.lpstrCustomFilter = NULL;
            open.lpstrFile = filebuff;
            open.lpstrFile[0] = '\0';
            open.nMaxFile = 256;
            open.nFilterIndex = 1;
            open.lpstrInitialDir = NULL;
            open.lpstrTitle = "Select An Image File\0";
            open.nMaxFileTitle = strlen("Select an image file\0");
            open.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER;

Then use

if (GetOpenFileName(&open))
{
 printf("File name:%s", open.lpstrFile);
}

The above code selects an image file, replace the lpstrFilter value to filter extensions, lpstrTitle and nMaxFileTitle() to your needs.

Here is the OPENFILENAME stuct documentation

All the properties are necessary for the dialog to show up!

Suraj S
  • 1,019
  • 7
  • 18
  • then i define the structure at the start of the program, and when the button pressed i put the GetOpenFileName() conditional? – Mark green Jun 30 '17 at 12:55
  • Yes exactly, be sure to use the appropriate lpstrFilter and title as suited to your needs – Suraj S Jun 30 '17 at 12:56
  • the function GetOpenFileNameA or GetOpenFileName both dont work in my c compiler, but in c++ their work. is their similar function for c? not c++! – Mark green Jul 01 '17 at 08:55
  • why isn't this marked, and why `-1` vote? It worked like charm. I will upvote this! – Mr. Wizard May 06 '20 at 19:20