Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 30.06.2011, 16:34   #1
БалаШагаЛ
Форумчанин
 
Регистрация: 11.02.2011
Сообщений: 131
По умолчанию Вопросы от новичка

Всем привет и здравствуйте. Вчера начал изучать WinApi, дошёл до примера исходного кода, переписал его к себе в компилятор. Вот код:
Код:
#include "windows.h"

LRESULT CALLBACK DCDemoWndProc(HWND,UINT,UINT,LONG);

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpszCmdParam,int nCmdShow)
{
    HWND hWnd;
    WNDCLASS WndClass;
    MSG Msg;
    char szClassName[]="DCDemo";
    WndClass.style=CS_HREDRAW|CS_VREDRAW;
    WndClass.lpfnWndProc=DCDemoWndProc;
    WndClass.cbClsExtra=0;
    WndClass.cbWndExtra=0;
    WndClass.hInstance=hInstance;
    WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
    WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
    WndClass.hbrBackground=(HBRUSH)(WHITE_BRUSH);
    WndClass.lpszMenuName="MyMenu";
    WndClass.lpszClassName=szClassName;
    if (!RegisterClass(&WndClass))
    {
        MessageBox(NULL,"Cannot register class","Error",MB_OK);
        return 0;
    }
    hWnd=CreateWindow(szClassName,"Program No 1",WS_OVERLAPPEDWINDOW,
                                 CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
                                 CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
    if (!hWnd)
    {
        MessageBox(NULL,"Cannot create window","Error",MB_OK);
        return 0;
    }
    ShowWindow(hWnd,nCmdShow);
    UpdateWindow(hWnd);
    while(GetMessage(&Msg,NULL,0,0))
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

LRESULT CALLBACK DCDemoWndProc(HWND hWnd,UINT Message,UINT wParam,LONG lParam)
{
    HDC hDC,hCompatibleDC;
    PAINTSTRUCT PaintStruct;
    HANDLE hBitmap,hOldBitmap;
    RECT Rect;
    BITMAP Bitmap;
    switch(Message)
    {
        case WM_PAINT:
        hDC=BeginPaint(hWnd,&PaintStruct);
        hBitmap=LoadImage(NULL,"MSDOGS.BMP",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
        GetObject(hBitmap,sizeof(BITMAP),&Bitmap);
        hCompatibleDC=CreateCompatibleDC(hDC);
        hOldBitmap=SelectObject(hCompatibleDC,hBitmap);
        GetClientRect(hWnd,&Rect);
        StretchBlt(hDC,0,0,Rect.right,Rect.bottom,hCompatibleDC,0,0,Bitmap.bmWidth,Bitmap.bmHeight,SRCCOPY);
        SelectObject(hCompatibleDC,hOldBitmap);
        DeleteObject(hBitmap);
        DeleteDC(hCompatibleDC);
        EndPaint(hWnd,&PaintStruct);
        return 0;
        case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hWnd,Message,wParam,lParam);
}
Компилятор почему-то выдаёт следующие ошибки:
undefined reference to 'GetObjectA@12'
undefined reference to 'CreateCompatibleDC@4'
undefined reference to 'SelectObject@8'
undefined reference to 'StretchBlt@44'
undefined reference to 'SelectObject@8'
undefined reference to 'DeleteObject@4'
undefined reference to 'DeleteDC@4'

Хотелось бы узнать:
1. Что они означают.
2. Как их исправить.
3. В книге, по которой я изучаю WinApi написано, что там рассмотрен язык для Windows98 и WindowsNT. У меня стоит WindowsXP. Есть ли различия между программированием в разных виндоузах и насколько они существены?

Последний раз редактировалось rpy3uH; 30.06.2011 в 17:00.
БалаШагаЛ вне форума Ответить с цитированием
Старый 30.06.2011, 21:00   #2
Dogmat
Пользователь
 
Регистрация: 12.06.2008
Сообщений: 76
По умолчанию

undefined reference означает, что функция на которую вы ссылаетесь в коде отсутстует в DLL. Все эти функции входят в gdi32.dll и дело тут похоже вот в чем. При экспорте функций различные компиляторы могут различным образом искажать имена функций, под которыми они потом хранятся в разделе экспорта. Соответственно эти же компиляторы ожидают, что в разделе экспорта эти функции будут значаться под искаженными именами. Я сам сижу на XP SP3, только что запустил BinDump и в разделе экспорта GDI32.dll функции перечислены без искажения (см. приложение). По всей видимости компилятор следуя собственным правилам ищет их под искаженными именами и не находит. Вообще у меня с этим слабо, но могу сказать что в Visual Studio с этим проблем не возникает. Только что проверил - компилируется. Вы какой компилятор используете? Можно попробовать эти функции объявить с неискаженными именами используя extern.

Попробуйте вставить после #include <windows.h>:
Код:
extern GetObjectA;
extern CreateCompatible;
extern SelectObject;
extern StretchBlt;
extern SelectObject;
extern DeleteObject;
extern DeleteDC;
Только, вместо названий впишите полную сигнатуру с параметрами и тип функции, как положено - объявите ее.

Но я совсем не уверен в том, что это поможет.
Вложения
Тип файла: txt dump.txt (25.8 Кб, 138 просмотров)

Последний раз редактировалось Dogmat; 01.07.2011 в 13:18.
Dogmat вне форума Ответить с цитированием
Старый 01.07.2011, 13:16   #3
Dogmat
Пользователь
 
Регистрация: 12.06.2008
Сообщений: 76
По умолчанию

Вообще самому интересно, как из подобных ситуаций выходить, неужели никто ничего больше не посоветует?
Dogmat вне форума Ответить с цитированием
Старый 01.07.2011, 13:42   #4
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

нужно подключать необходимые библиотеки, для ml(MSVC++) это или в коде через #pragma или в настройках проекта(библиотеки gdi32.lib)
для gcc в ком строке или опять же настройки проекта(если IDE какая то)
библиотека libgdi32.a(в ком строке писать -lgdi32)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 01.07.2011, 16:55   #5
execom
Редкий тунеядец
Форумчанин
 
Аватар для execom
 
Регистрация: 29.10.2006
Сообщений: 595
По умолчанию

Код:
    {
        case WM_PAINT:
        hDC=BeginPaint(hWnd,&PaintStruct);
        hBitmap=LoadImage(NULL,"MSDOGS.BMP",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
        GetObject(hBitmap,sizeof(BITMAP),&Bitmap);
        hCompatibleDC=CreateCompatibleDC(hDC);
        hOldBitmap=SelectObject(hCompatibleDC,hBitmap);
        GetClientRect(hWnd,&Rect);
        StretchBlt(hDC,0,0,Rect.right,Rect.bottom,hCompatibleDC,0,0,Bitmap.bmWidth,Bitmap.bmHeight,SRCCOPY);
        SelectObject(hCompatibleDC,hOldBitmap);
        DeleteObject(hBitmap);
        DeleteDC(hCompatibleDC);
        EndPaint(hWnd,&PaintStruct);
        return 0;
        case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
От этого участка кода я бы тоже не пришёл в восторг)) а компилятор и подавно... какой-то корявый вариант.

сишного сорца WinApi окошка под рукой не нашел вот на Delphi

Код:
program winmin;

const

  user32              = 'user32.dll';
  WM_DESTROY          = $0002;
  CS_VREDRAW          = 1;
  CS_HREDRAW          = 2;
  IDI_APPLICATION     = PChar(32512);
  IDC_ARROW           = PChar(32512);
  COLOR_BTNFACE       = 15;
  WS_OVERLAPPED       = 0;
  WS_CAPTION          = $C00000;
  WS_SYSMENU          = $80000;
  WS_THICKFRAME       = $40000;
  WS_MINIMIZEBOX      = $20000;
  WS_MAXIMIZEBOX      = $10000;

  WS_OVERLAPPEDWINDOW =(
    WS_OVERLAPPED
  or WS_CAPTION
  or WS_SYSMENU
  or WS_THICKFRAME
  or WS_MINIMIZEBOX
  or WS_MAXIMIZEBOX
  );

type

  TWndClassEx = packed record
    cbSize        : Integer;
    style         : Integer;
    lpfnWndProc   : Pointer;
    cbClsExtra    : Integer;
    cbWndExtra    : Integer;
    hInstance     : integer;
    hIcon         : Integer;
    hCursor       : Integer;
    hbrBackground : Integer;
    lpszMenuName  : PChar;
    lpszClassName : PChar;
    hIconSm       : Integer;
  end;

  TPoint = packed record
    X: Longint;
    Y: Longint;
  end;

  TMSG = packed record
    hwnd    : Integer;
    message : Integer;
    wParam  : Longint;
    lParam  : Longint;
    time    : Integer;
    pt      : TPoint;
  end;

procedure PostQuitMessage(nExitCode: Integer); stdcall; external user32 name 'PostQuitMessage';
function DefWindowProc(hWnd: Integer; Msg: Integer; wParam: Longint; lParam: Longint): LongInt; stdcall; external user32 name 'DefWindowProcA';
function RegisterClassEx(const WndClass: TWndClassEx): Word; stdcall; external user32 name 'RegisterClassExA';
function ShowWindow(hWnd: Integer; nCmdShow: Integer): BOOLEAN; stdcall; external user32 name 'ShowWindow';
function GetMessage(var lpMsg: TMsg; hWnd: Integer; wMsgFilterMin, wMsgFilterMax: Integer): BOOLEAN; stdcall; external user32 name 'GetMessageA';
function TranslateMessage(const lpMsg: TMsg): BOOLEAN; stdcall; external user32 name 'TranslateMessage';
function DispatchMessage(const lpMsg: TMsg): Longint; stdcall; external user32 name 'DispatchMessageA';
function LoadIcon(hInstance: Integer; lpIconName: PChar): Integer; stdcall; external user32 name 'LoadIconA';
function LoadCursor(hInstance: Integer; lpCursorName: PAnsiChar): Integer; stdcall; external user32 name 'LoadCursorA';
function CreateWindowEx(dwExStyle: Integer; lpClassName: PChar; lpWindowName: PChar; dwStyle: Integer; X, Y, nWidth, nHeight: Integer; hWndParent: Integer; hMenu: Integer; hInstance: Integer; lpParam: Pointer): Integer; stdcall; external user32 name 'CreateWindowExA';

var
  wc      : TWndClassEx;
  MainWnd : Integer;
  Mesg    : TMsg;

function WindowProc(wnd:Integer; Msg : Integer; Wparam:Longint; Lparam:Longint):LongInt; stdcall;
Begin
  if msg=wm_destroy then
    Begin
     postquitmessage(0);
     Result:=0;
     exit;
    End
   else Result:=DefWindowProc(wnd,msg,wparam,lparam);
End;

Procedure RegCls;
begin
  wc.cbSize:=sizeof(wc);
  wc.style:=cs_hredraw or cs_vredraw;
  wc.lpfnWndProc:=@WindowProc;
  wc.cbClsExtra:=0;
  wc.cbWndExtra:=0;
  wc.hInstance:=1;
  wc.hIcon:=LoadIcon(0,idi_application);
  wc.hCursor:=LoadCursor(0,idc_arrow);
  wc.hbrBackground:=COLOR_BTNFACE+1;
  wc.lpszMenuName:=nil;
  wc.lpszClassName:='WinMin : Main';
  RegisterClassEx(wc);
end;

Procedure Run;
begin
  RegCls;
  MainWnd:=CreateWindowEx ( 0, 'WinMin : Main', 'WinMin', ws_overlappedwindow, 100, 150, randint(400), 250, 0, 0, 1, nil);
  ShowWindow(MainWnd,1);
  While GetMessage(Mesg,0,0,0) do
    begin
      TranslateMessage(Mesg);
      ///Место для кода
      DispatchMessage(Mesg);
    end;
end;

Begin
Run
end.
execom вне форума Ответить с цитированием
Старый 01.07.2011, 19:39   #6
Vago
Форумчанин
 
Регистрация: 15.01.2010
Сообщений: 948
По умолчанию

Цитата:
Сообщение от execom Посмотреть сообщение
Код:
    {
        case WM_PAINT:
        hDC=BeginPaint(hWnd,&PaintStruct);
        hBitmap=LoadImage(NULL,"MSDOGS.BMP",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
        GetObject(hBitmap,sizeof(BITMAP),&Bitmap);
        hCompatibleDC=CreateCompatibleDC(hDC);
        hOldBitmap=SelectObject(hCompatibleDC,hBitmap);
        GetClientRect(hWnd,&Rect);
        StretchBlt(hDC,0,0,Rect.right,Rect.bottom,hCompatibleDC,0,0,Bitmap.bmWidth,Bitmap.bmHeight,SRCCOPY);
        SelectObject(hCompatibleDC,hOldBitmap);
        DeleteObject(hBitmap);
        DeleteDC(hCompatibleDC);
        EndPaint(hWnd,&PaintStruct);
        return 0;
        case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
От этого участка кода я бы тоже не пришёл в восторг)) а компилятор и подавно...
Простите, а от чего здесь "не придёт в восторг" компилятор?
Vago вне форума Ответить с цитированием
Старый 03.07.2011, 12:40   #7
БалаШагаЛ
Форумчанин
 
Регистрация: 11.02.2011
Сообщений: 131
По умолчанию

Всем спасибо огромное за помощь!
Код:
extern int GetObjectA(void*,int,void*);
extern HDC CreateCompatibleDC(HDC);
extern void* SelectObject(HDC*,void*);
extern BOOL StretchBlt(HDC*,int,int,int,int,HDC*,int,int,int,int,DWORD);
extern BOOL DeleteObject(void*);
extern BOOL DeleteDC(HDC*);
Вставил, не помогло, выдаёт те же ошибки. Использую Code Blocks. Лучше, думаю, просто поставить Visual Studio. В Code Blocks-е и других проблем хватает.
БалаШагаЛ вне форума Ответить с цитированием
Старый 03.07.2011, 12:47   #8
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

вы мой пост не видели?
там ведь описано решение.
библиотеки->добавить и выбрать libgdi32.a

с таким подходом и в студии не выйдет ничего(правда там по умолчанию они подключены, но чуть шаг влево, выйдут теже ошибки)
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 03.07.2011, 21:42   #9
БалаШагаЛ
Форумчанин
 
Регистрация: 11.02.2011
Сообщений: 131
По умолчанию

Если я правильно понял, то надо просто добавить #pragma <gdi32.lib> в код. Не помогло. Видимо, я неправильно понял.
БалаШагаЛ вне форума Ответить с цитированием
Старый 03.07.2011, 22:46   #10
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

мдя, читаете вы очень не внимательно:
1)#pragma comment(lib,"gdi32.lib")
2)я же сказал что это только для студийного компилятора.
для CodeBlocks смотрите настройки проекта.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Вопросы новичка Tyfun Помощь студентам 1 08.09.2010 08:07
Вопросы от новичка valenina Общие вопросы Delphi 10 31.05.2010 09:35
Вопросы новичка(C++) NetGod Общие вопросы C/C++ 22 17.04.2009 22:49
Вопросы новичка! Dimixis Помощь студентам 16 19.06.2007 10:35