1

Consider the following code:

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
    PWSTR pCmdLine, int nCmdShow) {

    MSG  msg;    
    HWND hwnd;
    WNDCLASSW wc;

    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.lpszClassName = L"Window";
    wc.hInstance     = hInstance;
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wc.lpszMenuName  = NULL;
    wc.lpfnWndProc   = WndProc;
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);

    RegisterClassW(&wc);
    hwnd = CreateWindowW(wc.lpszClassName, L"Window",
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                100, 100, 350, 250, NULL, NULL, hInstance, NULL);  

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0)) {

        DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
    WPARAM wParam, LPARAM lParam) {

    switch(msg) {

      case WM_DESTROY:

          PostQuitMessage(0);
          break;
    }

    return DefWindowProcW(hwnd, msg, wParam, lParam);
}

This creates a blank window, I want to reproduce this but using the main entry point instead of wWinMain.

The following code works, but it feels very hacky:

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int main(int argc, HINSTANCE argv) {

    MSG  msg;    
    HWND hwnd;
    WNDCLASSW wc;

    wc.style         = CS_HREDRAW | CS_VREDRAW;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.lpszClassName = L"Window";
    wc.hInstance     = argv;
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wc.lpszMenuName  = NULL;
    wc.lpfnWndProc   = WndProc;
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);

    RegisterClassW(&wc);
    hwnd = CreateWindowW(wc.lpszClassName, L"Window",
                WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                100, 100, 350, 250, NULL, NULL, hInstance, NULL);  

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&msg, NULL, 0, 0)) {

        DispatchMessage(&msg);
    }

    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
    WPARAM wParam, LPARAM lParam) {

    switch(msg) {

      case WM_DESTROY:

          PostQuitMessage(0);
          break;
    }

    return DefWindowProcW(hwnd, msg, wParam, lParam);
}

Is there a better way?

Xantium
  • 11,201
  • 10
  • 62
  • 89
  • 2
    You may find [this question](https://stackoverflow.com/questions/21718027/getmodulehandlenull-vs-hinstance) worth reading. – WhozCraig Jul 18 '19 at 09:18
  • @WhozCraig That is exactly what I am looking for thank you. Could you please consider leaving an answer so that I can accept it. – Xantium Jul 18 '19 at 09:30
  • 1
    `main` is the user program entry point for a console application. `WinMain` is the user program entry point for a Windows application. So why do you want `main` as entry point? Just use `WinMain`. – Paul Ogilvie Jul 18 '19 at 10:14
  • @PaulOgilvie I can't do that. I want to design a wrapper that creates a gui on multiple platforms. I want it to work for both Linux and Windows. On Windows it will call the functions for the WinApi and on Linux it will call GTK, The user will be therfore need to use the `main` entry point because that works on both, compared to WinMain that will only work on Windows. HINSTANCE is not cross platform, but I adapt my code so that it will be used as required on the specific platform. – Xantium Jul 18 '19 at 10:29
  • 1
    Just create two main files, one for windows and one for your other platform(s). Your whole apporach as shown uses windows, such as `WNDCLASS` and `RegisterClass`, so it is already windows-specific. You also say you adapt your code for the different platforms, now why not this too? Sounds to me you want to solve the wrong proble,. – Paul Ogilvie Jul 18 '19 at 10:39
  • use `(HINSTANCE)&__ImageBase` – RbMm Jul 18 '19 at 11:07

1 Answers1

4

You can get the .exe HMODULE/HINSTANCE with GetModuleHandle(0).

The real Windows entrypoint has no parameters, the C run-time calls GetModuleHandle for you when using WinMain.

wsman
  • 68
  • 4
  • or can use linker defined symbol *__ImageBase* if use link.exe - so `(HINSTANCE)&__ImageBase` – RbMm Jul 18 '19 at 11:08
  • *The real Windows entrypoint has no parameters* - this is not rue. real exe entry point have 1 parameter - pointer to *PEB* – RbMm Jul 18 '19 at 11:10