Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: WinAPI Регистрация своего контрола.  (Прочитано 13941 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Rulik
Помогающий

ru
Offline Offline

« : 06-07-2005 12:27 » 

Люди есть такая задача.
Надо создать и зарегестрировать глобальный класс окна.
Выглядит это приблизительно так

extern InitEditEx(HINSTANCE hInstance);

LRESULT CALLBACK EditExWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

CREATESTRUCT CreateStruct;
//===============================================================================
int WINAPI InitEditEx(HINSTANCE hInstance)
{
   HWND   hWnd = NULL;
   TCHAR   szWindowClass[]=L"EditEx";      // The window class name

   WNDCLASS   wc;

    wc.style         = CS_GLOBALCLASS;
    wc.lpfnWndProc      = (WNDPROC) EditExWndProc;
    wc.cbClsExtra      = 0;
    wc.cbWndExtra      = 0;
    wc.hInstance      = hInstance;
    wc.hIcon         = 0;
    wc.hCursor         = 0;
    wc.hbrBackground   = 0;
    wc.lpszMenuName      = 0;
    wc.lpszClassName   = szWindowClass;

   return RegisterClass(&wc);
}

//===============================================================================
//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND   - process the application menu
//  WM_PAINT   - Paint the main window
//  WM_DESTROY   - post a quit message and return
//
//
LRESULT CALLBACK EditExWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   HDC hdc;
   int wmId, wmEvent;
   PAINTSTRUCT ps;

   switch (message)
   {
      case WM_CREATE:
         memcpy(&CreateStruct,(LPCREATESTRUCT) lParam,sizeof(CreateStruct));
         break;
      case WM_PAINT:
         RECT rt;
         hdc = BeginPaint(CreateStruct.hwndParent, &ps);
          GetClientRect(CreateStruct.hwndParent, &rt);
         DrawText(hdc, L"Test", _tcslen(L"Test"), &rt,
            DT_SINGLELINE | DT_VCENTER | DT_CENTER);
         EndPaint(CreateStruct.hwndParent, &ps);
         break;
      case WM_DESTROY:
         PostQuitMessage(0);
         break;
      case WM_ACTIVATE:
            // Notify shell of our activate message
           break;
      case WM_SETTINGCHANGE:
           break;
      default:
         return DefWindowProc(CreateStruct.hwndParent, message, wParam, lParam);
   }
   return 0;
}

//===============================================================================

Но как только я создаю этот контрол в родительском окне, остальные контроли не прорисовываются пока на них
не кликнеш мышкой!
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 06-07-2005 12:42 » 

Ну первый вопрос. А зачем ты ее вообше делаеш глобально. Если в одном приложении она может сушествовать только в одном экземпляре. Так как любой повторный вызов CreateWindow будет затирать твою переменную CREATESTRUCT CreateStruct; ?
Второй вопрос. А зачем ты рисуеш на родительском окне в своем контроле. Когда родитель отрисовался. Все WM_PAINT родительского окна в очереди уничтожаются.
Зачем ты отдаеш управление тут DefWindowProc(CreateStruct.hwndParent, message, wParam, lParam); родительскому окну?

Еше один артефакт: переменную  wc.hbrBackground   надо или определить любой кистью или отрабатывать сообшение WM_ERASEBKGND
иначе фон у твоего окна не будет сушествовать.

Есть артефакт с контролом мыши. Но помоему Виндовс выставит курсор по умолчанию.
« Последнее редактирование: 06-07-2005 13:18 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Rulik
Помогающий

ru
Offline Offline

« Ответ #2 : 07-07-2005 12:19 » 

Я исправил

#include <windows.h>

extern InitEditEx(HINSTANCE hInstance);

LRESULT CALLBACK EditExWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

CREATESTRUCT CreateStruct;
unsigned char CursorType=1;
//===============================================================================
int WINAPI InitEditEx(HINSTANCE hInstance)
{
   HWND   hWnd = NULL;
   TCHAR   szWindowClass[]=L"EditEx";      // The window class name

   WNDCLASS   wc;

//   WM_DRAWFRAME = RegisterWindowMessage("WM_DRAWFRAME");

    wc.style         = CS_GLOBALCLASS;
    wc.lpfnWndProc      = (WNDPROC) EditExWndProc;
    wc.cbClsExtra      = 0;
    wc.cbWndExtra      = 0;
    wc.hInstance      = hInstance;
    wc.hIcon         = 0;
    wc.hCursor         = 0;
    wc.hbrBackground   = 0;
    wc.lpszMenuName      = 0;
    wc.lpszClassName   = szWindowClass;

   return RegisterClass(&wc);
}

//===============================================================================
int WINAPI PaintEditExWindow(HWND hWnd)//&#206;&#242;&#240;&#232;&#241;&#238;&#226;&#234;&#224; &#238;&#234;&#237;&#224;
{
   HDC hdc;
   PAINTSTRUCT ps;
   RECT rt;

   hdc = BeginPaint(hWnd, &ps);
//   GetWindowRect(hWnd, &rt);
   GetClientRect(hWnd, &rt);
//   DrawText(hdc, L"Test", _tcslen(L"Test"), &rt,DT_SINGLELINE | DT_VCENTER | DT_CENTER);

   Rectangle(hdc,rt.left,rt.top,rt.right,rt.bottom);

   switch (CursorType)
   {
   case 0:
      Rectangle(hdc,10,10,20,20);
      break;
   case 1:
      Ellipse(hdc,10,10,20,20);
      break;
   }

   EndPaint(hWnd, &ps);
 return 0;
}
//===============================================================================
void CALLBACK CursorTimer(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime)
{
   switch (CursorType)
   {
   case 0:
      CursorType=1;
      break;
   case 1:
      CursorType=0;
      break;
   }

   InvalidateRect(hwnd,NULL,FALSE);
}
//===============================================================================
//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND   - process the application menu
//  WM_PAINT   - Paint the main window
//  WM_DESTROY   - post a quit message and return
//
//
LRESULT CALLBACK EditExWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   int wmId, wmEvent;

   switch (message)
   {
      case WM_CREATE://&#209;&#238;&#231;&#228;&#224;&#237;&#232;&#229; &#238;&#234;&#237;&#224;
         memcpy(&CreateStruct,(LPCREATESTRUCT) lParam,sizeof(CreateStruct));
         break;
      case WM_LBUTTONDOWN://&#192;&#234;&#242;&#232;&#226;&#224;&#246;&#232;&#255; &#238;&#234;&#237;&#224;
         SetTimer(hWnd,1,500,CursorTimer);
         break;
      case WM_KILLFOCUS://&#192;&#234;&#242;&#232;&#226;&#224;&#246;&#232;&#255; &#238;&#234;&#237;&#224;
         KillTimer(hWnd,1);
         break;
      case WM_GETFONT://&#199;&#224;&#239;&#240;&#238;&#241; &#241;&#232;&#241;&#242;&#229;&#236;&#251; &#232;&#237;&#244;&#238;&#240;&#236;&#224;&#246;&#232;&#232; &#238; &#232;&#241;&#239;&#238;&#235;&#252;&#231;&#243;&#229;&#236;&#238;&#236; &#248;&#240;&#232;&#244;&#242;&#229;
         return NULL;
         break;
      case WM_SIZE:
         return 0;
         break;
      case WM_MOVE:
         return 0;
         break;
      case WM_WINDOWPOSCHANGED:
         return 0;
         break;
      case WM_PAINT:
         PaintEditExWindow(hWnd);
         break;
//      default:
//         return DefWindowProc(CreateStruct.hwndParent, message, wParam, lParam);
   }
   return 0;
}

//===============================================================================
Окно стало отрисовываться нормально.
Но почемуто я не получаю сообщения типа WM_SETFOCUS или WM_KILLFOCUS
может подскажите?

А фон мне пока и ненужен. Мне бы получать юти сообщения.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #3 : 07-07-2005 19:44 » 

Попробуй в обработчике WM_LBUTTONDOWN поставить функцию SetFocus(hWnd); Твоя компонента просто не приобретает фокус ввода. Из за этого и нет сообшений.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Rulik
Помогающий

ru
Offline Offline

« Ответ #4 : 08-07-2005 15:01 » 

LRESULT CALLBACK EditExWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   int wmId, wmEvent;

   switch (message)
   {
      case WM_CREATE:
         memcpy(&CreateStruct,(LPCREATESTRUCT) lParam,sizeof(CreateStruct));
         break;
      case WM_LBUTTONDOWN:
         SetFocus(hWnd);
         break;
      case WM_SETFOCUS:
         SetTimer(hWnd,1,500,CursorTimer);
         break;
      case WM_KILLFOCUS:
         KillTimer(hWnd,1);
         break;
      case WM_GETFONT:
         return NULL;
         break;
      case WM_SIZE:
         return 0;
         break;
      case WM_MOVE:
         return 0;
         break;
      case WM_WINDOWPOSCHANGED:
         return 0;
         break;
      case WM_PAINT:
         PaintEditExWindow(hWnd);
         break;
//      default:
//         return DefWindowProc(CreateStruct.hwndParent, message, wParam, lParam);
   }
   return 0;
}

Но, WM_KILLFOCUS я не получаю!
Как зарегистрироваться чтоб как нормальный контрол получать сообщения!
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #5 : 08-07-2005 18:11 » 

Какие у тебя симптомы? Что именно происходит? Получаеш ли фокус вообше?
И еше два замечания.
1. Лучше сделать так
 case WM_LBUTTONDOWN:
         if (GetFocus() != hWnd) SetFocus(hWnd);
         break;

Иначе при любом клике на компоненту, будет посылаться запрос на фокус.
Цитата
If the function succeeds, the return value is the handle of the window that previously had the keyboard focus. If the hWnd parameter is invalid or the window is not associated with the calling thread's message queue, the return value is NULL.
Проверь, какой выход из функции SetFocus. Он должен быть хэндлом окна, от которого перехвачен фокус ввода.
Цитата
The SetFocus function sends a WM_KILLFOCUS message to the window that loses the keyboard focus and a WM_SETFOCUS message to the window that receives the keyboard focus. It also activates either the window that receives the focus or the parent of the window that receives the focus.
Как видиш WM_KILLFOCUS, посылается автоматически, когда перехватывается фокус ввода.


2. Зачем заремил  DefWindowProc(CreateStruct.hwndParent, message, wParam, lParam);
Да кстати оставил ошибку CreateStruct.hwndParent
« Последнее редактирование: 20-12-2007 21:12 от Алексей1153++ » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Rulik
Помогающий

ru
Offline Offline

« Ответ #6 : 09-07-2005 01:39 » 

WM_SETFOCUS  я получаю но как только кликаю по пустой форме я WM_KILLFOCUS не получаю.
Я бы этой ендой не стродал бы, еслиб начальство не доставало с новым контролом.
В котором нужно всего по маненьку. и причем надо чтоб было зарегино в системе глобально!
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #7 : 09-07-2005 06:23 » 

Я поиграюсь с твоими файлами у себя в машине.
Что касается CS_GLOBALCLASS, вот выдержка из MSDN
Цитата
Allows an application to create a window of the class regardless of the value of the hInstance parameter passed to the CreateWindow or CreateWindowEx function. If you do not specify this style, the hInstance parameter passed to the CreateWindow (or CreateWindowEx) function must be the same as the hInstance parameter passed to the RegisterClass function.
You can create a global class by creating the window class in a dynamic-link library (DLL) and listing the name of the DLL in the registry under the following keys:
    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Windows\APPINIT_DLLS
Whenever a process starts, the operating system loads the specified DLLs in the context of the newly started process before calling the main function in that process. The DLL must register the class during its initialization procedure and must specify the CS_GLOBALCLASS style.
т.е. CS_GLOBALCLASS позволяет просто регистрировать и запускать компоненту в разных hInstance. Если хочеш ее использовать в разных приложениях, то надо оформлять ввиде DLL и делать регистрацию в секции DLL_PROCESS_ATTACH библиотеки.
Еше одно замечание:  Лучше сведи все переменные твоего класса в одну структуру. И в WM_CREATE иницилизируй структуру динамически. И записывай адрес этой структуры через функцию SetWindowLong с параметром GWL_USERDATA. Когда нужна твоя структура, просто считывай адрес через функцию  GetWindowLong с тем же параметром.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #8 : 09-07-2005 07:22 » 

У тебя все работает, вот прога, которую я сделал на своем компе.
Main.cpp
Код:
//============================================================
// Name:         Rulik
// Description :
//============================================================
//---------------------------------------------------------------------------
#include <windows.h>
#include <windowsx.h>
#include "Rulik.h"
//---------------------------------------------------------------------------


static HWND MainWindow;
char szAppName[] = "EscButtom";
char szTitle[] = "Return";
HWND ChWnd1;
HWND ChWnd2;
HINSTANCE hIn;

bool Register(HINSTANCE);
HWND Create(HINSTANCE, int);

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

int MaxX;
int MaxY;
RECT rect;
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE hInst,
               HINSTANCE hPrevInst,
               LPSTR CmdParam,
               int nCmdShow)
{
   MSG Msg;
   hIn=hInst;

   if (!Register(hInst))
       return false;
   MainWindow=Create(hInst,nCmdShow);
   if (MainWindow==0)
       return false;

   while (GetMessage(&Msg,NULL,0,0))
      {
       TranslateMessage(&Msg);
       DispatchMessage(&Msg);
      }
   return Msg.wParam;
}
//---------------------------------------------------------------------------
bool Register(HINSTANCE hInst)
{
   WNDCLASS wc;

   wc.style         = CS_HREDRAW | CS_VREDRAW;
   wc.lpfnWndProc   = (WNDPROC) WndProc;
   wc.cbClsExtra    = 0;
   wc.cbWndExtra    = 0;
   wc.hInstance     = hInst;
   wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
   wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
   wc.hbrBackground = (HBRUSH) (1);
   wc.lpszMenuName  = NULL;
   wc.lpszClassName = szAppName;
   InitEditEx(hInst);
   return (RegisterClass(&wc) !=0);

}

HWND Create(HINSTANCE hInst, int nCmdShow)
{
   HWND hWindow = CreateWindow(szAppName, szTitle,
                               WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                               CW_USEDEFAULT, CW_USEDEFAULT,
                               CW_USEDEFAULT, CW_USEDEFAULT,
                               NULL, NULL, hInst, NULL);
   if (hWindow != NULL)
       {
        ShowWindow(hWindow, nCmdShow);
        UpdateWindow(hWindow);
       }
   return hWindow;
}


void OnDestroy(HWND hwnd)
{
   PostQuitMessage(0);
}


BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct)
{
    ChWnd1= CreateWindow(chRulik, NULL,
                               WS_CHILD | WS_VISIBLE,
                               5, 5,
                               50, 50,
                               hwnd, NULL, hIn, NULL);
    ChWnd2= CreateWindow(chRulik, NULL,
                               WS_CHILD | WS_VISIBLE,
                               60, 5,
                               50, 50,
                               hwnd, NULL, hIn, NULL);
return -1;
}

LRESULT CALLBACK WndProc(HWND hWindow, UINT Message,
                         WPARAM wParam, LPARAM lParam)
{
   switch(Message)
      {
       HANDLE_MSG(hWindow, WM_DESTROY,   OnDestroy);
   HANDLE_MSG(hWindow, WM_CREATE,   OnCreate);
       default:
          return DefWindowProc(hWindow, Message, wParam, lParam);
      }
}
//---------------------------------------------------------------------------

Rulik.h
Код:
#ifndef RULIK_H
#define RULIK_H
ATOM InitEditEx(HINSTANCE hInstance);
const TCHAR   chRulik[]="EditEx";      // The window class name
#endif

Rulik.cpp
Код:
#include <windows.h>
#include "Rulik.h"



LRESULT CALLBACK EditExWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);


unsigned char CursorType=1;
//==============================================================
ATOM InitEditEx(HINSTANCE hInstance)
{
   

   WNDCLASS   wc;
    wc.style         = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc      = (WNDPROC) EditExWndProc;
    wc.cbClsExtra      = 0;
    wc.cbWndExtra      = 0;
    wc.hInstance      = hInstance;
    wc.hIcon         = 0;
    wc.hCursor         = 0;
    wc.hbrBackground   = (HBRUSH) 1;
    wc.lpszMenuName      = 0;
    wc.lpszClassName   = chRulik;

   return RegisterClass(&wc);
}

//==================================================
int WINAPI PaintEditExWindow(HWND hWnd)
{
   HDC hdc;
   PAINTSTRUCT ps;
   RECT rt;

   hdc = BeginPaint(hWnd, &ps);
//   GetWindowRect(hWnd, &rt);
   GetClientRect(hWnd, &rt);
//   DrawText(hdc, L"Test", _tcslen(L"Test"), &rt,DT_SINGLELINE | DT_VCENTER | DT_CENTER);

   Rectangle(hdc,rt.left,rt.top,rt.right,rt.bottom);

   switch (CursorType)
   {
   case 0:
      Rectangle(hdc,10,10,20,20);
      break;
   case 1:
      Ellipse(hdc,10,10,20,20);
      break;
   }

   EndPaint(hWnd, &ps);
 return 0;
}
//===============================================================
void CALLBACK CursorTimer(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime)
{
   switch (CursorType)
   {
   case 0:
      CursorType=1;
      break;
   case 1:
      CursorType=0;
      break;
   }

   InvalidateRect(hwnd,NULL,FALSE);
}
//================================================
//
//  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND   - process the application menu
//  WM_PAINT   - Paint the main window
//  WM_DESTROY   - post a quit message and return
//
//
LRESULT CALLBACK EditExWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  // int wmId, wmEvent;
CREATESTRUCT *CS;
   switch (message)
   {
      case WM_CREATE:
CS = new CREATESTRUCT;
         memcpy(CS,(LPCREATESTRUCT) lParam,sizeof(CREATESTRUCT));
         SetWindowLong(hWnd, GWL_USERDATA, (LONG) CS);
         break;
      case WM_LBUTTONDOWN:
         if (GetFocus() != hWnd) SetFocus(hWnd);
         break;
      case WM_SETFOCUS:
         SetTimer(hWnd,1,500,CursorTimer);
         break;
      case WM_KILLFOCUS:
         KillTimer(hWnd,1);
         break;
      case WM_DESTROY:
CS= (CREATESTRUCT *) GetWindowLong(hWnd, GWL_USERDATA);
delete CS;
break;
      case WM_PAINT:
         PaintEditExWindow(hWnd);
         break;
      default:
         return DefWindowProc(hWnd, message, wParam, lParam);
   }
   return 0;
}

//================================================

Я сделал два окошка, и если поочередно по ним шелкать, фокус перемешается с одного в другой.
« Последнее редактирование: 09-07-2005 07:26 от Finch » Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #9 : 09-07-2005 08:27 » 

Да кстати, ты сделал мигание ради проверки, или хочеш получить курсор ввода. Если второе, то посмотри в MSDN тему Carets. Это уже реализовано в Виндовсе.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Rulik
Помогающий

ru
Offline Offline

« Ответ #10 : 09-07-2005 09:51 » 

Я все это пишу для WinCE. Ты не подскажешь как зарегестрировать глобально сообщение в системе под постоянным идентификатором?
Этот контрол будет в DLL и им будет пользоваться несколько приложений. Поэтому желательно иметь свои сообщения.
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #11 : 09-07-2005 09:59 » 

Цитата
The RegisterWindowMessage function defines a new window message that is guaranteed to be unique throughout the system. The returned message value can be used when calling the SendMessage or PostMessage function.

UINT RegisterWindowMessage(

    LPCTSTR lpString    // address of message string
   );   
 

Parameters

lpString

Points to a null-terminated string that specifies the message to be registered.

 

Return Values

If the message is successfully registered, the return value is a message identifier in the range 0xC000 through 0xFFFF.
If the function fails, the return value is zero.

Remarks

The RegisterWindowMessage function is typically used to register messages for communicating between two cooperating applications.
If two different applications register the same message string, the applications return the same message value. The message remains registered until the Windows session ends.
Only use RegisterWindowMessage when more than one application must process the same message. For sending private messages within a window class, an application can use any integer in the range WM_USER through 0x7FFF. (Messages in this range are private to a window class, not to an application. For example, predefined control classes such as BUTTON, EDIT, LISTBOX, and COMBOBOX may use values in this range.)
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #12 : 09-07-2005 10:10 » 

Можеш использовать такую схему:
Код:
#define WM_MYMESSAGE1 WM_USER+1
#define WM_MYMESSAGE2 WM_USER+2
#define WM_MYMESSAGE3 WM_USER+3
#define WM_MYMESSAGE4 WM_USER+4
Да они не будут уникальны в системе, но для твоей компоненты они будут уникальны. 
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Rulik
Помогающий

ru
Offline Offline

« Ответ #13 : 09-07-2005 11:04 » 

Спасибо за помощь, разобрался я с сообщениями и курсор стандартный включил. Спасиб тебе Finch! Отлично
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines