1414
Типичные вопросы [контролы]
На этой станице помещены ответы на вопросы, которые я сам мучительно (или легко) находил, я не думаю, что ответы исчерпывающие, и если Вы найдёте, что что-нибудь дисанирует с Вашими представлениями, давайте обсудим и найдём лучшие решения... Кроме того, часто ответ может зависеть от версии как OS так и Visual FoxPro, проверить всё на всех версиях и платформах для меня просто непосильно. Изначально этот список был исключительно для VFP 5.0, в то время как сейчас это только VFP 7.0/8.0, я мог где-нибудь и пропустить упоминание о версии, и если Вы найдёте несоответствия, сообщите пожалуйста мне.

 

Вопрос: Как вернуть числовое кодовое значение из ComboBox с двумя полями (символьное название, числовой код) для записи его в числовое поле таблицы, т.е. когда данные таблицы для ComboBox являются подчинёнными некоторой родительской таблицы по числовому кодовому полю? 

Ответ: Для версии Visual FoxPro 3.0 исчерпывающий ответ зарегистрированные пользователи могут найти в Internet по адресу: http://msdn.microsoft.com/library/ (анг.) в разделе Preodicals/FoxTalks/Volume 8 1996 : (http://www.pinpub.com/foxtalk/) статья Use a Combo Box to Select Foreign Keys http://msdn.microsoft.com/library/periodic/period96/D1/FT0896.htm (для краткости детали я здесь не обсуждаю). В версии Visual FoxPro 5.0a достаточно у ComboBox установить свойство BoundTo в значение: .T., отличное от .F. (default), конечно же определив свойства: BoundColumn, ControlSource, RowSource и RowSourceType соответствующим образом.

Вопрос: Каким образом я могу отображать подчинённое множество записей в Grid для некоторой записи в родительской таблице, если источником данных для Grid является View? 

Ответ: Принципиально имеется две возможности сделать это: использовать параметрический запрос в качестве источника данных к Grid или установить для него соответствующее свойство Filter. Каждый из этих случаев может существенно отличаться объёмом пересылаемой информации между сервером данных и клиентом, нужно также отметить, что в первом случае Вам потребуется явное применение функции REQUERY() для источника данных Grid после перемещения указателя текущей записи в родительской таблице, чтобы повторно выполнить запрос данных согласно изменившемся условиям. См. также
Q142974 Views.exe - One-To-Many Form Using a Parameterized View на Microsoft.com
Q156169 HOWTO: Ignore Parameters in View or Query If Blank

Вопрос: Как добавить CheckBox и ComboBox в качестве отображаемых элементов столбцов в Grid? 

Ответ: Прежде всего, следует отметить, что для CheckBox тип данных соответствующего ему поля источника данных должен быть логическим, в то время как использование ComboBox подразумевает, что Вы определите для него свойства: RowSource, RowSourceType, Style (данные, отображаемые в ComboBox или подчинённый источник данных) и ControlSource, BoundColumn, BoundTo (возвращаемое значение, т.е. редактируемое поле таблицы-источника данных Grid, для которого ComboBox собственно и отображает подчинённое значение).
Для добавления CheckBox проще всего использовать Builder для Grid (вызов по правой кнопке мыши Builder…), где на закладке Layout следует переустановить значение Control type в CheckBox для соответствующего столбца Grid. Проследите, чтобы перед вызовом Builder используемые таблицы были предварительно открыты, поскольку он может анализировать содержание только открытых таблиц, предоставляя Вам информацию для настройки.
Элементы CheckBox или ComboBox можно добавить и во время редактирования Grid. Для этого выберите Ваш столбец в качестве активного (Columni в окне Properties) и перетащите нужный Вам элемент (CheckBox или ComboBox) из Forms Controls Toolbar в первую строку Grid. Если теперь Вы раскроете ComboBox объектов в окне Properties, то увидите, что выбранный Вами элемент добавлен в качестве элемента столбца (сразу после Text1), хотя и не является пока активным. Наконец, чтобы активизировать добавленный Вами элемент переустановите свойство CurrentControl для столбца Columni на нужный Вам элемент.

Вопрос: Я хотел бы по щелчку мыши на заголовке столбца Grid переустанавливать активный индекс у источника. Переустанавливать индекс получается, но я при этом теряю текущую запись. Как я должнен сделать, чтобы запись после переустановки индекса оставалась прежней? 

Ответ: В VFP6.0 магическое действие в Grid.Header.Click() следующее:
LOCAL lnRecNo
lnRecNo = IIF(!EOF(), RECNO(), 0)
ThisForm.DataEnvironment.cursor1.Order = "Column_Order" 
*-- or SET ORDER TO TAG Column_Order
WITH This.Parent.Parent
    .ActivateCell(1, .ActiveColumn)
    IF lnRecNo # 0
        GO (lnRecNo)
    ELSE
        GO TOP 
    ENDIF
    .Refresh()
ENDWITH
См. также раздел "PRB: Incremental Search with Grid Causes Screen Flicker" в MSDN

Вопрос: У меня не удаляется запись в Grid, подскажите как я это должен сделать корректно. 

Ответ: Если у Вас установлена блокировка в блокировку записи (buffering record) и свойство Grid.DeleteMark сброшено (.F.), то Вам может помочь следующий код:
...
WITH ThisForm
    IF VARTYPE(.ActiveControl) = "O";
            AND .ActiveControl.BaseClass == "Grid";
            AND !INLIST(CURSORGETPROP("Buffering"), 4, 5);
            AND !.ActiveControl.DeleteMark
        *-- Grid с DeleteMark = .F. и buffering record имеет проблему 
        *-- при удалении записи, необходимо временно
        *--  установить свойство DeleteMark = .T.
        LOCAL loGrid
        loGrid = .ActiveControl
        loGrid.DeleteMark = .T.
    ENDIF
ENDWITH
lnRecNo = RECNO()
DELETE
llError = !TABLEUPDATE(.T.)
IF TYPE("loGrid") = "O"
    loGrid.DeleteMark = .F.
ENDIF
...
См. также http://support.microsoft.com/kb/q191641/

Вопрос: Как в объекте Grid удалить (скрыть с экрана), а позже восстановить, на прежнее место, колонку (объект Column)? При этом, необходимо чтобы при удалении колонки на ее место вставала колонка справа. 

Ответ: Попробуйте следующее в методе Header1.Click():
WITH This.Parent
    IF .Visible 
        .Visible = .F.
        .Width = 0
    ELSE
        .Visible = .T.
        .Width = 75 && -- или прежний размер
                    ** -- из предварительно созданного свойства-массива формы  
    ENDIF
ENDWITH

можете установить Grid1.GridLineColor = RGB(128, 128, 128), чтобы скрытая колонка "не бросалась в глаза"... как, надеюсь, самый простой вариант...

Вопрос: Я хочу добавить данные в ComboBox, так чтобы иметь два столбца, у меня нет присоединённого источника данных, данные я хотел бы добавлять программно, но у мкня ничего не получается. Как это можно сделать? 

Ответ: Если я правильно понял проблему, Вам нужно использовать: для первой колонки: .AddItem(...) ...и для всех остальных: .AddListItem(...)

Вопрос: Размещаю на форме ActiveX-ный компонент ImageList. Прописываю в нём имеджы. Размещаю на той же форме ActiveX-ный компонент Toolbar. Делаю в нём ссылку на ImageList. Завершаю редактирование Toolbara. Открываю его снова, ссылка - none. Что с этим делать?  

Ответ: Выполняйте инициализацию свойства MyForm.MyToolbar1.Object.ImageList в runtime, подобно следующему:
#DEFINE tbrDefault	0
#DEFINE tbrCheck	1
#DEFINE tbrButtonGroup	2
#DEFINE tbrSeparator	3
#DEFINE tbrPlaceholder	4
#DEFINE tbrDropDown	5 

#DEFINE MAXBUTTONS	2 

LOCAL lcCurKey, loButton, lnCntImg, lnCntBtn
lnCntImg = 0
WITH ThisForm.MyToolbar1.Object
	.ImageList = ThisForm.MyImageList.Object
	WITH .Buttons
		FOR lnCntBtn = 1 TO MAXBUTTONS
			lnCntImg = lnCntImg+1
			lcCurKey = SYS(2015)
			.Add(,lcCurKey)
			loButton = .Item(.Count)
			WITH loButton
				.Image = lnCntImg 
				* ... etc
			ENDWITH
			loButton = NULL
		ENDFOR	
	ENDWITH
ENDWITH
Обратите внимание на два момента:
использование ключевого слова Object, чтобы адресоваться не к VFP-покрытию объекта, а непосредственно к его свойству/методу
чтобы получить ссылку на Button я использую Buttons.Item(Buttons.Count) а не возвращаемое значение методом Add()
Подозреваю, что для этого тривиального объекта, это всё смотрится как "лишние навороты", но лишь до некоторых пор..., и конечно всё зависит от версии объектов... :-)
См. также Q163803 в MSDN

Вопрос: У меня не получается обратиться к UDF в ControlSource столбца Grid в форме. 

Ответ: Попробуйте использовать следующее выражение: (UDF(Table.Field1[,...])[...]). Обратите внимание на "лишние" внешние скобки и фактический параметр в UDF: поле-таблицы.

Вопрос: Хочу показать значение memo-поля таблицы в столбце Grid, однако у меня отображается только слово Memo, а мне нужно значение. Как это можно сделать? 

Ответ: Самый простой способ добавить "лишние" внешние круглые скобки подобно ThisForm.MyGrid.ColumnX.ControlSource = "(MyTable.MyMemoField)", также можно вставить Editbox в качестве CurrentControl столбца и отображать значение memo-поля через него.

Вопрос: Хочу многострочный заголовок столбцов в Grid. Что можно сделать? 

Ответ: См ID: Q133164 В MSDN или на http://www.microsoft.ru/catalog/article.asp?article_id={4CA8A85C-B996-11D4-9DAA-00508B8B6DC3} или http://support.microsoft.com/kb/q133164/

Вопрос: В приложении использую ActiveX control, создаю дискрибутив используя VFP Setup Wizard. После установки на клиенте получаю ошибку: OLE error code 0x80040112: Appropriate license for this class not found. Можно ли это как-то побороть?  

Ответ: см. "INFO: OLE Control Licensing in Visual FoxPro" в MSDN а также "HOWTO: Register an ActiveX Control (.ocx) Manually".

Вопрос: У меня Windows NT, пытаюсь из RichTextBox Control организовать печать, но не удаётся из CommonDialog Control получить device context hDC property, чтобы передать первому в метод SelPrint. Другими словами: можно ли вывести информацию из RichTextBox Control на печать? 

Ответ: Хм... посмотрел... действительно не работает :-( ... Однако, попробуй чего-нибудь типа:
#DEFINE C_DRVNAME "winspool"
DECLARE LONG CreateDC IN Gdi32.dll ;
  STRING @ lpszDriver, ; &&// driver name
  STRING @ lpszDevice, ; &&// device name
  STRING @ lpszOutput, ; &&// not used; should be NULL
  STRING @ lpInitData  &&// optional printer data
LOCAL nCntPrn
LOCAL ARRAY laPrinters[1,2]
nCntPrn = APRINTERS(laPrinters)
IF nCntPrn = 0
 RETURN .F.
ENDIF
LOCAL lcPrinter, lhDC
lcPrinter = laPrinters[1,1]
lhDC = CreateDC(C_DRVNAME, lcPrinter, NULL, NULL)
IF lhDC = 0
 RETURN .F.
ENDIF
ThisForm.Olecontrol1.Object.SelPrint(lhDC)
CLEAR DLLS
C_DRVNAME как я понял из MSDN CreateDC() для Windows 95/98 должно быть NULL в то время как у меня тоже NT, а по сему "winspool"

Вопрос: Могу ли я как-нибудь вставить Internet Explorer в форму VFP? 

Ответ: Попробуйте что-нибудь подобно следующему:
#DEFINE C_URL	"http://vfpdmur.narod.ru/" &&- Insert your URL here

RELEASE ox
PUBLIC ox
ox = CreateObject("MyInternetExplorer")
IF TYPE('ox') = 'O' AND !ISNULL(ox)
	WITH ox
		.oWeb.Navigate(C_URL,,"_self")
		IF !.Visible
			.Visible = .T.
		ENDIF
	ENDWITH
ELSE
	MESSAGEBOX("Error in CreateObject('MyInternetExplorer')", 16, 'Error')
ENDIF

DEFINE CLASS MyInternetExplorer AS form
	ADD OBJECT oWeb AS CWebExp
	Caption = "My Internet Explorer"
	PROCEDURE Init
		WITH ThisForm
			.Width = SYSMETRIC(21)*3/4
			.Height = SYSMETRIC(22)*3/4
			.Resize()
		ENDWITH
	ENDPROC
	PROCEDURE Resize
		ThisForm.oWeb.resize()
	ENDPROC
ENDDEFINE

DEFINE CLASS CWebExp AS olecontrol
	OleClass = "Shell.Explorer"
	PROCEDURE Resize
		WITH This
			.Width = ThisForm.Width - 1
			.Height = ThisForm.Height - 1
		ENDWITH
	ENDPROC
	PROCEDURE Refresh
		NODEFAULT
	ENDPROC
ENDDEFINE

Вопрос: Нужен h-файл с определением констант для Excel 2000 Где можно взять? 

Ответ: Где взять именно для Excel 2000 не знаю, для Excel 97 есть на http://www.universalthread.com Однако, есть ещё такая утилита "GetConstants - COM constants to .h file" на http://www.west-wind.com/files/getconstants.zip

Вопрос: SelectOnEntry on MouseClick for TextBox как организовать? 

Ответ: Попробуйте выполнить KEYBOARD '{SHIFT+END}' в событии MyTextBox.GotFocus()

Вопрос: Не получается в ActivX Comctl2.MonthView.2 воспользоваться DayBold(), возвращает "Function argument value, type, or count is invalid (Error 11)". Можно это как-нибудь побороть? 

Ответ: Попробуйте как-нибудь так:
 
WITH ThisForm.Olecontrol1.Object 
	FOR lnCnt = 1 TO 42 
		.DayBold(TTOC(.VisibleDays(lnCnt))) = .T. 
	ENDFOR 
ENDWITH 
 
 
Hosted by uCoz