www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Simple GUI test

reply smithfox <ssm.fox gmail.com> writes:
I wrote a simple GUI test

code:
//=======================
import std.c.windows.windows;
import std.c.stdio;

extern(Windows)
int WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
{
/*
    try
    {
        int a = 0;
    }catch (Object o)        // catch any uncaught exceptions
    {
        int b = 0;
    }
*/
    MessageBoxA(null, "aabc", "Error",MB_OK | MB_ICONEXCLAMATION);
    return 0;
}
//=======================

When I compile the code, screen output following Error:
Error 42: Symbol Undefined __acrtused
OPTLINK : Warning 134: No Start Address

But when I uncomment the comment code, the compiler can pass.

My questions is:
1. What's mean  "Symbol Undefined __acrtused" in above codes.
2. Whether all GUI program using D must have WinMain function?
3. If we can write GUI program without WinMain, how to get 
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow
??
Apr 22 2007
next sibling parent "Christof Schardt" <christof schardt.info> writes:
This is a working example, maybe your questions
become obsolete by that.

--------------------------------------------------------------------------
-- winsamp.de
--------------------------------------------------------------------------
/* Compile with:
 * dmd winsamp gdi32.lib winsamp.def
 */

import std.c.windows.windows;
import std.c.stdio;

const int IDC_BTNCLICK = 101;
const int IDC_BTNDONTCLICK = 102;

extern(Windows)
int WindowProc(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam)
{
 switch (uMsg)
 {
     case WM_COMMAND:
     {
  switch (LOWORD(wParam))
  {
      case IDC_BTNCLICK:
   if (HIWORD(wParam) == BN_CLICKED)
    MessageBoxA(hWnd, "Hello, world!", "Greeting",
     MB_OK | MB_ICONINFORMATION);
   break;
      case IDC_BTNDONTCLICK:
   if (HIWORD(wParam) == BN_CLICKED)
   {
       MessageBoxA(hWnd, "You've been warned...", "Prepare to GP fault",
        MB_OK | MB_ICONEXCLAMATION);
       *(cast(int*) null) = 666;
   }
   break;
  }
  break;
     }

     case WM_PAINT:
     {
  static char[] text = "D Does Windows";
  PAINTSTRUCT ps;
  HDC dc = BeginPaint(hWnd, &ps);
  RECT r;
  GetClientRect(hWnd, &r);
  HFONT font = CreateFontA(80, 0, 0, 0, FW_EXTRABOLD, FALSE, FALSE,
   FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
   DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");
  HGDIOBJ old = SelectObject(dc, cast(HGDIOBJ) font);
  SetTextAlign(dc, TA_CENTER | TA_BASELINE);
  TextOutA(dc, r.right / 2, r.bottom / 2, text, text.length);
  SelectObject(dc, old);
  EndPaint(hWnd, &ps);
  break;
     }
     case WM_DESTROY:
  PostQuitMessage(0);
  break;

     default:
  break;
 }
 return DefWindowProcA(hWnd, uMsg, wParam, lParam);
}

int doit()
{
 HINSTANCE hInst = GetModuleHandleA(null);
 WNDCLASS wc;
 wc.lpszClassName = "DWndClass";
 wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
 wc.lpfnWndProc = &WindowProc;
 wc.hInstance = hInst;
 wc.hIcon = LoadIconA(cast(HINSTANCE) null, IDI_APPLICATION);
 wc.hCursor = LoadCursorA(cast(HINSTANCE) null, IDC_CROSS);
 wc.hbrBackground = cast(HBRUSH) (COLOR_WINDOW + 1);
 wc.lpszMenuName = null;
 wc.cbClsExtra = wc.cbWndExtra = 0;
 RegisterClassA(&wc);

 HWND hWnd, btnClick, btnDontClick;
 hWnd = CreateWindowA("DWndClass", "Just a window", WS_THICKFRAME |
  WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE,
  CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, HWND_DESKTOP,
  cast(HMENU) null, hInst, null);
 assert(hWnd);

 btnClick = CreateWindowA("BUTTON", "Click Me", WS_CHILD | WS_VISIBLE,
  0, 0, 100, 25, hWnd, cast(HMENU) IDC_BTNCLICK, hInst, null);

 btnDontClick = CreateWindowA("BUTTON", "DON'T CLICK!", WS_CHILD | 
WS_VISIBLE,
  110, 0, 100, 25, hWnd, cast(HMENU) IDC_BTNDONTCLICK, hInst, null);

 MSG msg;
 while (GetMessageA(&msg, cast(HWND) null, 0, 0))
 {
  TranslateMessage(&msg);
  DispatchMessageA(&msg);
 }

 return 1;
}

/**********************************************************/

/* Note the similarity of this code to the console D startup
 * code in \dmd\src\phobos\dmain2.d
 * You'll also need a .def file with at least the following in it:
 * EXETYPE NT
 * SUBSYSTEM WINDOWS
 */

extern (C) void gc_init();
extern (C) void gc_term();
extern (C) void _minit();
extern (C) void _moduleCtor();
extern (C) void _moduleUnitTests();

extern (Windows)
int WinMain(HINSTANCE hInstance,
 HINSTANCE hPrevInstance,
 LPSTR lpCmdLine,
 int nCmdShow)
{
    int result;

    gc_init();   // initialize garbage collector
    _minit();   // initialize module constructor table

    try
    {
 _moduleCtor();  // call module constructors
 _moduleUnitTests(); // run unit tests (optional)

 result = doit(); // insert user code here
    }

    catch (Object o)  // catch any uncaught exceptions
    {
 MessageBoxA(null, cast(char *)o.toString(), "Error",
      MB_OK | MB_ICONEXCLAMATION);
 result = 0;  // failed
    }

    gc_term();   // run finalizers; terminate garbage collector
    return result;
}

--------------------------------------------------------------------------
-- winsamp.def
--------------------------------------------------------------------------
EXETYPE NT
SUBSYSTEM WINDOWS
Apr 22 2007
prev sibling next sibling parent "Lionello Lunesu" <lionello lunesu.remove.com> writes:
You should just keep using "main" (instead of WinMain), but you should 
instruct  the compiler that you don't want a console window by adding a .def 
file for your project. The DMD distribution ZIP contains a sample, if I'm 
not mistaken.

L.

"smithfox" <ssm.fox gmail.com> wrote in message 
news:f0fv9s$1baf$1 digitalmars.com...
I wrote a simple GUI test

 code:
 //=======================
 import std.c.windows.windows;
 import std.c.stdio;

 extern(Windows)
 int WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
 {
 /*
    try
    {
        int a = 0;
    }catch (Object o)        // catch any uncaught exceptions
    {
        int b = 0;
    }
 */
    MessageBoxA(null, "aabc", "Error",MB_OK | MB_ICONEXCLAMATION);
    return 0;
 }
 //=======================

 When I compile the code, screen output following Error:
 Error 42: Symbol Undefined __acrtused
 OPTLINK : Warning 134: No Start Address

 But when I uncomment the comment code, the compiler can pass.

 My questions is:
 1. What's mean  "Symbol Undefined __acrtused" in above codes.
 2. Whether all GUI program using D must have WinMain function?
 3. If we can write GUI program without WinMain, how to get
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow
 ?? 

Apr 22 2007
prev sibling next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
smithfox wrote:
 I wrote a simple GUI test

Try the sample gui app \dmd\samples\d\winsamp.d
 My questions is:
 1. What's mean  "Symbol Undefined __acrtused" in above codes.

http://www.digitalmars.com/ctg/acrtused.html
 2. Whether all GUI program using D must have WinMain function?
 3. If we can write GUI program without WinMain, how to get 
     HINSTANCE hInstance,
     HINSTANCE hPrevInstance,
     LPSTR lpCmdLine,
     int nCmdShow
 ??

Apr 22 2007
prev sibling parent reply smithfox <ssm.fox gmail.com> writes:
Thanks all,

Actually, My simple GUI test code is from winsamp.d, and I also have written
def file. If I use main function instead of WinMain. Everything is OK.

(1) I'm confused that how to write startup code in a GUI program without 3rd
lib/framework(like dfl,dwt).

D language suggests to use main function as starup code in GUI program,
but why the "winsamp.d"  starup with "WinMain"? 

(2) And I found following codes in "winsamp.d".
extern (C) void gc_init();
extern (C) void gc_term();
extern (C) void _minit();
extern (C) void _moduleCtor();
extern (C) void _moduleUnitTests();

I searched all codes in dfl source and dwt source , but didn't found above
codes.

(3) How to write a standard GUI code just like using win32 SDK?

Thanks
Apr 23 2007
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
smithfox wrote:
 Thanks all,
 
 Actually, My simple GUI test code is from winsamp.d, and I also have written
def file. If I use main function instead of WinMain. Everything is OK.
 
 (1) I'm confused that how to write startup code in a GUI program without 3rd
lib/framework(like dfl,dwt).
 
 D language suggests to use main function as starup code in GUI program,
 but why the "winsamp.d"  starup with "WinMain"? 
 
 (2) And I found following codes in "winsamp.d".
 extern (C) void gc_init();
 extern (C) void gc_term();
 extern (C) void _minit();
 extern (C) void _moduleCtor();
 extern (C) void _moduleUnitTests();
 
 I searched all codes in dfl source and dwt source , but didn't found above
codes.
 
 (3) How to write a standard GUI code just like using win32 SDK?
 
 Thanks

I'm a bit out of it at the moment, and I'm not 100% sure what's wrong, but I think I know what the problem is. See, main() functions in D aren't simply jumped into when the executable is run. When your D program is run, there's another main() function that gets called *first*; for the sake of discussion, let's call this pre-main. Pre-main's job is to start up and shut down the garbage collector, call module constructors, run unit tests and wrap your main() function in try{}catch(){} handlers so that uncaught exceptions can be printed to the user. *However* if your program uses WinMain as the entry point, none of this is done. That means that when your program starts at WinMain, the garbage collector isn't running, none of the imported modules have been initialised, etc. This is why you need to write all that extra horrible code: since you're bypassing pre-main, you need to do it's job manually. All those extern(C) functions are either part of the standard library (like gc_init and gc_term) or generated by the compiler when you make your program, and are what pre-main calls to set everything up. Basically, you should copy+paste everything from line 106 down in winsamp.d into your program. You can play around with line 135 to change what function is called to actually "run" your program, and what you pass to it. Once you've taken care of all that nasty startup code, everything should work like any other Win32 GUI program--no need for dfl or dwt or anything else. You might want to grab the win32 headers from (this is off the top of my head, so it might be off): dsource.org/projects/bindings. Hope that helps :) -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Apr 23 2007