На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
[!] Как относитесь к модерированию на этом форуме? Выскажите свое мнение здесь
Модераторы: Qraizer
  
> В чём секрет glut? , Не получается сделать то же самое при помощи Winapi/opengl
    Всем доброго времени суток, у меня есть очередной вопрос. У меня не получается разобраться, как работает glut. Он был выбран, потому что приложение на glut32.dll корректно работает на всех моих машинах. Я хотел повторить то же самое, но без glut32.dll. Был написан код:

    ExpandedWrap disabled
      #include <windows.h>
      #include <gl/GL.h>
      #pragma comment(lib, "opengl32.lib")
       
      #define CLASSNOTREGISTERED 1
      #define WINDOWNOTCREATED 2
      #define MESSAGENOTGOT 3
      #define OGLCONTEXNOTCREATED 4
      #define OGLCONTEXNOTMADECURRENT 5
       
      HWND hWnd;
      HDC hDc;
       
      LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
      {
          switch (message)
          {
              case WM_DESTROY:
                  PostQuitMessage(0);
                  break;
              case WM_PAINT:
                  glClearColor(0.0, 0.0, 0.0, 1.0);
                  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                  glBegin(GL_TRIANGLES);
                  glColor3f(1.0, 0.0, 0.0);
                  glVertex3f(0.25, 0.25, 0.0);
                  glColor3f(0.0, 1.0, 0.0);
                  glVertex3f(0.75, 0.25, 0.0);
                  glColor3f(0.0, 0.0, 1.0);
                  glVertex3f(0.75, 0.75, 0.0);
                  glEnd();
                  glFlush();
                  SwapBuffers(hDc);
                  break;
              default:
                  return DefWindowProc(hWnd, message, wParam, lParam);
          }
          return 0;
      }
       
      ATOM RegMyWindowClass(HINSTANCE hInst, LPCTSTR lpzClassName)
      {
          WNDCLASS wcWindowClass = { 0 };
          wcWindowClass.lpfnWndProc = (WNDPROC)WndProc;            // адрес ф-ции обработки сообщений
          wcWindowClass.style = CS_HREDRAW | CS_VREDRAW;           // стиль окна
          wcWindowClass.hInstance = hInst;                         // дискриптор экземпляра приложения
          wcWindowClass.lpszClassName = lpzClassName;              // название класса
          wcWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW);     // загрузка курсора
          wcWindowClass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;// загрузка цвета окон
          return RegisterClass(&wcWindowClass);                    // регистрация класса
      };
       
      int WinInit(HINSTANCE hInstance)
      {
          LPCTSTR lpzClass = TEXT("My Window Class!");
       
          if (!RegMyWindowClass(hInstance, lpzClass))
          {
              return CLASSNOTREGISTERED;
          };
       
          hWnd = CreateWindow(lpzClass, TEXT("Dialog Window"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 800, 600, NULL, NULL, hInstance, NULL);
       
          if (!hWnd)
          {
              return WINDOWNOTCREATED;
          };
       
          return 0;
      }
       
      int WinLoop()
      {
          MSG msg = { 0 };
          int iGetOk = 0;
          while ((iGetOk = GetMessage(&msg, NULL, 0, 0)) != 0)
          {
              if (iGetOk == -1) return MESSAGENOTGOT;
              TranslateMessage(&msg);
              DispatchMessage(&msg);
          };
          return msg.wParam;
      };
       
      int WinOGLInit()
      {
          
          PIXELFORMATDESCRIPTOR pfd;
          ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
          //Версия с сайта 1:
          /*pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
          pfd.nVersion = 1;
          pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_TYPE_RGBA;
          pfd.iPixelType = 24;
          pfd.cDepthBits = 32;
          pfd.iLayerType = PFD_MAIN_PLANE;*/
          
          //Версия с сатйта 2
          pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
          pfd.nVersion = 1;
          pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
          pfd.iPixelType = PFD_TYPE_RGBA;
          pfd.cColorBits = 24;
       
          hDc = GetDC(hWnd);
       
          int nPixelFormat = ChoosePixelFormat(hDc, &pfd);
          SetPixelFormat(hDc, nPixelFormat, &pfd);
       
       
          HGLRC hglrc = wglCreateContext(hDc);
          if (!hglrc)
          {
              return GetLastError();
          };
       
          if (!wglMakeCurrent(hDc, hglrc))
          {
              return OGLCONTEXNOTMADECURRENT;
          };
       
          
          return 0;
      };
       
      int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
      {
          int initresult = WinInit(hInstance);
       
          if (initresult != 0)
          {
              return initresult;
          };
       
          initresult = WinOGLInit();
          if (initresult != 0)
          {
              return initresult;
          };
       
          return WinLoop();  
      }


    Результат оставляет желать лучшего (обе версии). Во время перерисовок на одной машине (NVidia) окно мограет белым и скорость перерисовок очень низкая, на другой машине (Intel HD) вообще не рисует. Я решил узнать секрет glut. Попробовал прикрутить к проекту glut - но он намертво завязан на glut.dll. Исходный код всех функций вроде как есть, но всё равно требует glut32.lib и glut32.dll. Попробовал пособирать кусочки кода в один файл, чтоб точно скомпилировалось, но через один вечер работы запарился и понял, что что-то я не то делаю. Из ситуации вижу три выхода:

    1) Как-то настроить проект так, чтобы он подключал glut/freeglut и компилировал их, при этом не требовал .lib/.dll. И отлаживать программу.
    2) Найти или сделать самому файл, который работает так, как описано в пункте 1. Это у меня не получилось, хотя может нужно больше времени.
    3) Отладчиком (таким, который показывает ассемблерные коды, не знаю, как это называется) смотреть, какие функции opengl32.dll и winapi вызываются из glut32.dll. Если честно, не хочется это делать.

    Просто забросить и использовать glut32.dll не очень хочется. Заранее спасибо.
      Я так понимаю, freeglut - хорошая альтернатива glut. В чем тогда проблема? Качаешь исходник freeglut, собираешь либы и подключаешь к своему проекту. В поставке freeglut вроде есть инструкции для всего этого, не?
        k.sovailo, а вот это - что такое ?
        ExpandedWrap disabled
                 case WM_PAINT:
                      glClearColor(0.0, 0.0, 0.0, 1.0);
                      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                      glBegin(GL_TRIANGLES);
                      glColor3f(1.0, 0.0, 0.0);
                      glVertex3f(0.25, 0.25, 0.0);
                      glColor3f(0.0, 1.0, 0.0);
                      glVertex3f(0.75, 0.25, 0.0);
                      glColor3f(0.0, 0.0, 1.0);
                      glVertex3f(0.75, 0.75, 0.0);
                      glEnd();
                      glFlush();
                      SwapBuffers(hDc);
                      break;
          Цитата ЫукпШ @

          Это рисование самого простого треугольника в ответ на сообщение о необходимости перерисовки окна. Очистка буфера, рисование и замена буфера. Наверное, я не понял вопрос.

          Добавлено
          JoeUser, хотел уже сказать, что проделывал эти шаги, но проверил ещё раз. Всё точно так же, как и в glut, только freeglut собирается только на х64. В результате я подключаю в проект .lib и .h и получаю "бла-бла-бла нет freeglutd.dll". Если её положить возле экзешника - никаких проблем, но это не то, чего я хочу. На всякий случай:

          ExpandedWrap disabled
            #include <glut.h>
             
            void renderScene(void) {
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
             
                glBegin(GL_TRIANGLES);
                glVertex3f(-0.5, -0.5, 0.0);
                glVertex3f(0.0, 0.5, 0.0);
                glVertex3f(0.5, -0.5, 0.0);
                glEnd();
             
                glutSwapBuffers();
            }
             
            int main(int argc, char **argv) {
             
                // инициализация
                glutInit(&argc, argv);
                glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
                glutInitWindowPosition(100, 100);
                glutInitWindowSize(400, 400);
                glutCreateWindow("Урок 1");
             
                // регистрация обратных вызовов
                glutDisplayFunc(renderScene);
             
                // Основной цикл GLUT
                glutMainLoop();
             
                return 0;
            }


          В то же время в README.Win32 написано: ...If you are using the DLL version of "freeglut"...
          То есть можно как-то использовать не-ДЛЛ-версию? Не могу понять, как.

          Добавлено
          ЫукпШ, может Вы про то, что каждый раз вызывается glClearColor? Есть косяк. Убрал - всё точно так же.
            Цитата k.sovailo @
            В то же время в README.Win32 написано: ...If you are using the DLL version of "freeglut"...
            То есть можно как-то использовать не-ДЛЛ-версию? Не могу понять, как.


            Там есть упоминание о "freeglut_static.lib" - следовательно статик-версия собираться должна...

            1) Читай внимательно README.cmake
            2) В одном из проектов есть сборочный файл под все версии, просто посмотри что и как там делают:

            ExpandedWrap disabled
              # This file is part of MXE. See LICENSE.md for licensing information.
               
              PKG             := freeglut
              $(PKG)_WEBSITE  := https://freeglut.sourceforge.io/
              $(PKG)_IGNORE   :=
              $(PKG)_VERSION  := 3.0.0
              $(PKG)_CHECKSUM := 2a43be8515b01ea82bcfa17d29ae0d40bd128342f0930cd1f375f1ff999f76a2
              $(PKG)_SUBDIR   := freeglut-$($(PKG)_VERSION)
              $(PKG)_FILE     := freeglut-$($(PKG)_VERSION).tar.gz
              $(PKG)_URL      := https://$(SOURCEFORGE_MIRROR)/project/freeglut/freeglut/$($(PKG)_VERSION)/$($(PKG)_FILE)
              $(PKG)_DEPS     := cc
               
              define $(PKG)_UPDATE
                  $(WGET) -q -O- 'https://sourceforge.net/projects/freeglut/files/freeglut/' | \
                  $(SED) -n 's,.*freeglut-\([0-9][^>]*\)\.tar.*,\1,p' | \
                  head -1
              endef
               
              define $(PKG)_BUILD
                  cd '$(BUILD_DIR)' && '$(TARGET)-cmake' '$(SOURCE_DIR)' \
                      -DFREEGLUT_GLES=OFF \
                      -DFREEGLUT_BUILD_DEMOS=OFF \
                      -DFREEGLUT_REPLACE_GLUT=ON \
                      -DFREEGLUT_BUILD_STATIC_LIBS=$(CMAKE_STATIC_BOOL) \
                      -DFREEGLUT_BUILD_SHARED_LIBS=$(CMAKE_SHARED_BOOL)
                  $(MAKE) -C '$(BUILD_DIR)' -j '$(JOBS)' VERBOSE=1
                  $(MAKE) -C '$(BUILD_DIR)' -j 1 install VERBOSE=1
               
                  '$(TARGET)-gcc' \
                      -W -Wall -Werror -ansi -pedantic \
                      '$(TEST_FILE)' -o '$(PREFIX)/$(TARGET)/bin/test-freeglut.exe' \
                      `'$(TARGET)-pkg-config' glut --cflags --libs`
              endef
              Цитата k.sovailo @
              Цитата ЫукпШ @

              Это рисование самого простого треугольника в ответ на сообщение о необходимости перерисовки окна. Очистка буфера, рисование и замена буфера.

              Вот на это я и хотел обратить внимание.
              Чтобы с максимальной вероятностью прекратить любые видео-эффекты,
              надо отделить операцию рисования от операции вывода.
              А у тебя эти операции объединены вместе.
              Надо, чтобы из WM_PAINT готовое изображение копировалось в окно.
              Тогда такая операция будет производиться максимально быстро.
              -----
              Ещё рекомендуется обрабатывать сообщение "WM_ERASEBKGND".
              Сообщение отредактировано: ЫукпШ -
                Цитата JoeUser @

                Действительно, есть упоминание. Всего-то и надо было:
                ExpandedWrap disabled
                  #define FREEGLUT_STATIC 1
                  #include <glut.h>

                Теперь буду надеяться, что разберусь, в чём "магия". Тему пока не закрываю.
                  ЫукпШ, я ковырялся-ковырялся, но так и не смог сделать ещё один буфер. wglCreateContext напрочь отказывается создавать контекст, если ей передают hDc чего-то, кроме формы. Пробовал с HBITMAP, пробовал с Gdiplus::Bitmap и Gdiplus::Graphics, не работает. Не могу применить ваш совет.

                  Уточнил флаги, которые использует freeglut, лучше не стало. Хотя у меня такое чувство, что это какой-то обманный манёвр. Потому что freeglut сначала создаёт контекст и сразу же высвобождает, а потом создаёт его только где-то в дебрях (отслеживал отладчиком), кода которых у меня нет. Так что придётся либо писать 64-битную программу с freeglut, либо 32-битную с glut и таскать библиотеки, либо ковыряться дальше. В каждом варианте свои минусы.

                  ExpandedWrap disabled
                    #include <windows.h>
                    #include <gl/GL.h>
                    #define _USE_MATH_DEFINES  
                    #include <cmath>
                    #pragma comment(lib, "opengl32.lib")
                     
                    #define CLASSNOTREGISTERED 1
                    #define WINDOWNOTCREATED 2
                    #define MESSAGENOTGOT 3
                    #define OGLCONTEXNOTCREATED 4
                    #define OGLCONTEXNOTMADECURRENT 5
                    #define PIXELFORMATNOTSET 6
                     
                    class Application
                    {
                        public:
                            HINSTANCE hInstance;
                            HWND hWnd;
                            HDC windowDC;
                            HGLRC hglrc;
                            LPCTSTR classname;
                            WNDCLASS wndclass;
                    };
                     
                    Application app;
                    float angle = 1.0;
                     
                     
                    void DrawScreen()
                    {
                        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                        glBegin(GL_TRIANGLES);
                     
                        glColor3f(1.0, 0.0, 0.0);
                        glVertex3f(0.5*sin(angle), 0.5*cos(angle), 0.0);
                     
                        glColor3f(0.0, 1.0, 0.0);
                        glVertex3f(0.5*sin(angle + 2 * M_PI / 3), 0.5*cos(angle + 2 * M_PI / 3), 0.0);
                     
                        glColor3f(0.0, 0.0, 1.0);
                        glVertex3f(0.5*sin(angle + 4 * M_PI / 3), 0.5*cos(angle + 4 * M_PI / 3), 0.0);
                     
                        glEnd();
                        glFlush();
                        SwapBuffers(app.windowDC);
                    };
                     
                    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
                    {
                        switch (message)
                        {
                            case WM_DESTROY:
                                PostQuitMessage(0);
                                break;
                            case WM_PAINT:
                                DrawScreen();
                                break;
                            default:
                                return DefWindowProc(hWnd, message, wParam, lParam);
                        }
                        return 0;
                    }
                     
                    int WinLoop()
                    {
                        MSG msg = { 0 };
                        int iGetOk = 0;
                        while ((iGetOk = GetMessage(&msg, NULL, 0, 0)) != 0)
                        {
                            if (iGetOk == -1) return MESSAGENOTGOT;
                            TranslateMessage(&msg);
                            DispatchMessage(&msg);
                        };
                        return msg.wParam;
                    };
                     
                    ATOM RegMyWindowClass()
                    {
                        ZeroMemory(&(app.wndclass), sizeof(WNDCLASS));
                     
                        app.wndclass.lpfnWndProc = (WNDPROC)WndProc;            // адрес ф-ции обработки сообщений
                        app.wndclass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;// стиль окна
                        app.wndclass.hInstance = app.hInstance;                 // дискриптор экземпляра приложения
                        app.wndclass.lpszClassName = app.classname;             // название класса
                        app.wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);     // загрузка курсора
                        app.wndclass.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;// загрузка цвета окон
                        return RegisterClass(&app.wndclass);                    // регистрация класса
                    };
                     
                    bool SetWindowFormat()
                    {
                        PIXELFORMATDESCRIPTOR pfd;
                        ZeroMemory(&pfd, sizeof(PIXELFORMATDESCRIPTOR));
                     
                        int flags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
                     
                        /* Specify which pixel format do we opt for... */
                        pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
                        pfd.nVersion = 1;
                        pfd.dwFlags = flags;
                     
                        pfd.iPixelType = PFD_TYPE_RGBA;
                        pfd.cRedBits = 8;
                        pfd.cGreenBits = 8;
                        pfd.cBlueBits = 8;
                        pfd.cAlphaBits = 0;//(fgState.DisplayMode & GLUT_ALPHA) ? 8 : 0
                     
                        pfd.cColorBits = 24;
                        pfd.cRedShift = 0;
                        pfd.cGreenShift = 0;
                        pfd.cBlueShift = 0;
                        pfd.cAlphaShift = 0;
                        pfd.cAccumBits = 0;//(fgState.DisplayMode & GLUT_ACCUM) ? 1 : 0
                        pfd.cAccumRedBits = 0;
                        pfd.cAccumGreenBits = 0;
                        pfd.cAccumBlueBits = 0;
                        pfd.cAccumAlphaBits = 0;
                     
                        /* Hmmm, or 32/0 instead of 24/8? */
                        pfd.cDepthBits = 24;
                        pfd.cStencilBits = 8;
                     
                        pfd.cAuxBuffers = 0;//(BYTE)fghNumberOfAuxBuffersRequested()
                        pfd.iLayerType = 0;//layer_type
                        pfd.bReserved = 0;
                        pfd.dwLayerMask = 0;
                        pfd.dwVisibleMask = 0;
                        pfd.dwDamageMask = 0;
                     
                        pfd.cColorBits = (BYTE)GetDeviceCaps(app.windowDC, BITSPIXEL);
                     
                     
                        int nPixelFormat = ChoosePixelFormat(app.windowDC, &pfd);
                        if (nPixelFormat == 0)
                            return false;
                     
                        SetPixelFormat(app.windowDC, nPixelFormat, &pfd);
                     
                        return true;
                    };
                     
                    int WinInit()
                    {
                        app.classname = TEXT("My Window Class!");
                     
                        if (!RegMyWindowClass())
                            return CLASSNOTREGISTERED;
                     
                        if ((app.hWnd = CreateWindow(app.classname, TEXT("Dialog Window"), WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 800, 600, NULL, NULL, app.hInstance, NULL)) == 0)
                            return WINDOWNOTCREATED;
                     
                        app.windowDC = GetDC(app.hWnd);
                        if (!SetWindowFormat())
                            return PIXELFORMATNOTSET;
                     
                        return 0;
                    }
                     
                    int WinOGLInit()
                    {
                        app.hglrc = wglCreateContext(app.windowDC);
                        if (app.hglrc == 0)
                            return GetLastError();
                     
                        if (!wglMakeCurrent(app.windowDC, app.hglrc))
                            return OGLCONTEXNOTMADECURRENT;
                     
                        return 0;
                    };
                     
                    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
                    {
                        app.hInstance = hInstance;
                        int initresult;
                        
                        initresult = WinInit();
                        if (initresult != 0)
                            return initresult;
                     
                        initresult = WinOGLInit();
                        if (initresult != 0)
                            return initresult;
                     
                        return WinLoop();  
                    }
                  Сообщение отредактировано: k.sovailo -
                    Цитата k.sovailo @
                    ЫукпШ, я ковырялся-ковырялся, но так и не смог сделать ещё один буфер. wglCreateContext напрочь отказывается создавать контекст, если ей передают hDc чего-то, кроме формы.

                    Вот, я посмотрел.
                    Ты используешь :
                    ExpandedWrap disabled
                      class Application
                      {
                          public:
                              HINSTANCE hInstance;
                              HWND hWnd;
                              HDC windowDC;
                              HGLRC hglrc;
                              LPCTSTR classname;
                              WNDCLASS wndclass;
                      };

                    Если в структуру подставить HDC какого-нибудь memdc ?
                    Созданного на WINAPI.
                    Всё должно работать.
                    А потом в WM_PAINT просто выполним "BitBlt" в соответствии с размерами прямоугольника,
                    передаваемого в Paint - структуре.
                      ЫукпШ
                      ExpandedWrap disabled
                        app.windowDC = GetDC(app.hWnd);
                        SetOGLPixelFormat(app.windowDC));//pfd и всё остальное - в этой функции
                        app.bufferDC = CreateCompatibleDC(app.windowDC);
                        app.hBuffer = CreateCompatibleBitmap(app.bufferDC, 800, 600);
                        SetOGLPixelFormat(app.bufferDC);
                        SelectObject(app.bufferDC, app.hBuffer);//советовали на одном форуме
                        wglMakeCurrent(app.bufferDC, NULL);//советовали на другом форуме
                        app.hglrc = wglCreateContext(app.bufferDC);//возвращает 0


                      Не работает. Если создавать битмап в контексте окна, тоже не работает. Я правильно понял?
                      Сообщение отредактировано: k.sovailo -
                        Я тут провёл ещё несколько попыток и понял, что лучше доверить эту работу freeglut. Закончилось на том, что я подкорректировал код, добавил getHWND() и написал функцию динамического подключения freeglut.dll. Спасибо за внимание.
                          Цитата k.sovailo @
                          Не работает. Если создавать битмап в контексте окна, тоже не работает. Я правильно понял?

                          Трудно мне без отладки по тексту сказать точно, где ошибка.
                          я делал так:
                          ExpandedWrap disabled
                            //..
                             HDC d_c   = ::CreateDC(_T("DISPLAY"),NULL,NULL,NULL);
                             HDC memdc = ::CreateCompatibleDC  (d_c);
                             
                             RECT rc;  ::GetWindowRect (::GetDesktopWindow(), &rc);
                             
                            // размер скрина:
                             int sizex  = (rc.right   - rc.left) ;
                             int sizey  = (rc.bottom  - rc.top)  ;
                             
                             HBITMAP hbit = ::CreateCompatibleBitmap (d_c, sizex, sizey);  ::SelectObject (memdc, hbit);
                             HBRUSH brush = ::CreateSolidBrush  (someColor);               ::SelectObject (memdc, brush);
                             
                             ::PatBlt(memdc,0,0,sizex,sizey,PATCOPY); // закрасить memdc кистью brush цвета someColor
                             
                             ::DeleteDC(d_c);
                            //...
                             
                            // в результате получили memdc размером с экран.
                            // зачищенный цветом  "someColor".
                            // функциями GDI там можно рисовать что угодно. Можно читать/писать посредством "BitBlt" любыми кусками.


                          Понятно, что лучше все эти объекты обернуть классами, поскольку попытка следить за ними "вручную"
                          скорее всего закончится утечкой ресурсов. Исходник в таком виде я представил для примера.
                          -----
                          Хочу заметить, что всё это имеет конкретное практическое применение.
                          Например, что делать, если рисование картинки занимает 1 секунду (или больше)?
                          Если сделать это из оконной процедуры, тогда на это время всё управление приложением
                          будет парализовано, в том числе перерисовка экрана. При этом сам вывод картинки
                          на экран (даже самый большой) может составить 1 [мс] или меньше.
                          Рисовать имиджи можно и в другом потоке.
                          Поэтому разделение этих 2-х операций весьма перспективное мероприятие.
                          Сообщение отредактировано: ЫукпШ -
                          0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                          0 пользователей:


                          Рейтинг@Mail.ru
                          [ Script execution time: 0,0523 ]   [ 19 queries used ]   [ Generated: 28.03.24, 19:32 GMT ]