[C con Clase] Problema al cargar un recurso en una dll

Steven Davidson steven en conclase.net
Mie Jun 27 19:53:22 CEST 2007


Hola Man,

El pasado 2007-06-27 16:20:13, Man Alvarez escribió:

MA> Hola Steven
MA> Steven podrías mandarme la prueba que mencionas que hiciste? Quisiera
MA> examinarla y quizás así descubra en que estoy fallando al crear la mía.

Sí. Expongo los contenidos de los ficheros más abajo.

MA> Mandé mi código a la lista te llegó? Estaba pensando que quizá sea por las

Me temo que no llegó el fichero.

MA> opciones que elegí cuando cree el proyecto, voy a probar creándola eligiendo
MA> otras opciones.

Es posible. Ten presente que tienes que crear dos proyectos: uno donde crear la DLL y otro para usar y probar la DLL. A la hora de usar la DLL, el enlazador típicamente crea una biblioteca de importación; por ejemplo, "dialogo_dll.lib" aparte de la DLL en sí: "dialogo_dll.dll". Deberías agregar esta biblioteca de importación al enlazador en tu proyecto.

También observa que cualquier programa que vaya a usar tu DLL seguirá una búsqueda establecida por MS-Windows. La búsqueda comienza en el mismo directorio del fichero ejecutado. Por lo tanto, recuerda copiar tu DLL a tal directorio para que tu programa automáticamente encuentre y cargue la DLL.


Espero que los programas posteriores te sirvan. Ten en cuenta que usé Dev-C++ para estas pruebas, pero no he tenido problema alguno a la hora de hacerlo mismo bajo VS.

Steven

---------------------------------

// Programa de prueba
// "dialogo_win_winmain.cpp"

#include <windows.h>
#include "dll_dialogo.h"

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
char szClassName[ ] = "WindowsApp";

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)

{
    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 color 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 */
           "Windows App",       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* 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, nFunsterStil);

    /* 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)
{
  static HWND hBoton;

    switch (message)                  /* handle the messages */
    {
      case WM_CREATE:
        hBoton = CreateWindowEx( 0L, "BUTTON", "Crear Diálogo",
                                 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
                                 20,20, 150,30,
                                 hwnd, (HMENU)IDOK, NULL, NULL );
      break;

      case WM_COMMAND:
        if( HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDOK )
        {
          if( !Dialog( NULL ) ) //GetModuleHandle("dll_dialogo.dll") ) )
            MessageBox( hwnd, "Dialog() == FALSE", "ERROR", MB_OK );
        }
      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;
}

---------------------------------

// "dll_dialogo.h"

#ifndef _DLL_H_
#define _DLL_H_

#if BUILDING_DLL
#  define DLLIMPORT __declspec (dllexport)
#else
#  define DLLIMPORT __declspec (dllimport)
#endif

// Función a exportar
DLLIMPORT HWND Dialog( HINSTANCE hInst );

#endif

---------------------------------

// "dll_dialogo_main.cpp"

#include <windows.h>

// Queremos crear la DLL: #definir BUILDING_DLL
#define BUILDING_DLL 1
#include "dll_dialogo.h"

// Función "privada" a la DLL  =>  no exportable
BOOL CALLBACK DialogoProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
  switch( uMsg )
  {
    case WM_INITDIALOG:
    return TRUE;

    case WM_COMMAND:
      EndDialog( hDlg, FALSE );
    return TRUE;
  }

  return FALSE;
}

// Función "pública" de la DLL
DLLIMPORT HWND Dialog( HINSTANCE hInst )
{
  return CreateDialog( hInst, "Dialogo", NULL, DialogoProc );
}

// Función homólogo a 'WinMain()' pero para DLL's
BOOL APIENTRY DllMain( HINSTANCE hInst, DWORD reason, LPVOID reserved )
{
  switch( reason )
  {
    case DLL_PROCESS_ATTACH:
    break;

    case DLL_PROCESS_DETACH:
    break;

    case DLL_THREAD_ATTACH:
    break;

    case DLL_THREAD_DETACH:
    break;
  }

  return TRUE;
}

---------------------------------

// "dll_dialogo.rc"

#include <windows.h>

Dialogo DIALOG 0, 0, 118, 48
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION
CAPTION "Diálogo de prueba"
FONT 8, "Helv"
BEGIN
 CONTROL "Mensaje de prueba", -1, "static", 
    SS_LEFT | WS_CHILD | WS_VISIBLE, 
    8, 9, 84, 8
 CONTROL "Aceptar", IDOK, "button", 
    BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 
    56, 26, 50, 14
END


Más información sobre la lista de distribución Cconclase